1 | use crate::call::PyCallArgs; |
2 | use crate::class::basic::CompareOp; |
3 | use crate::conversion::{AsPyPointer, FromPyObjectBound, IntoPyObject}; |
4 | use crate::err::{DowncastError, DowncastIntoError, PyErr, PyResult}; |
5 | use crate::exceptions::{PyAttributeError, PyTypeError}; |
6 | use crate::ffi_ptr_ext::FfiPtrExt; |
7 | use crate::instance::Bound; |
8 | use crate::internal::get_slot::TP_DESCR_GET; |
9 | use crate::internal_tricks::ptr_from_ref; |
10 | use crate::py_result_ext::PyResultExt; |
11 | use crate::type_object::{PyTypeCheck, PyTypeInfo}; |
12 | #[cfg (not(any(PyPy, GraalPy)))] |
13 | use crate::types::PySuper; |
14 | use crate::types::{PyDict, PyIterator, PyList, PyString, PyType}; |
15 | use crate::{err, ffi, Borrowed, BoundObject, IntoPyObjectExt, Python}; |
16 | use std::cell::UnsafeCell; |
17 | use std::cmp::Ordering; |
18 | use std::os::raw::c_int; |
19 | use std::ptr; |
20 | |
21 | /// Represents any Python object. |
22 | /// |
23 | /// Values of this type are accessed via PyO3's smart pointers, e.g. as |
24 | /// [`Py<PyAny>`][crate::Py] or [`Bound<'py, PyAny>`][Bound]. |
25 | /// |
26 | /// For APIs available on all Python objects, see the [`PyAnyMethods`] trait which is implemented for |
27 | /// [`Bound<'py, PyAny>`][Bound]. |
28 | /// |
29 | /// See |
30 | #[doc = concat!("[the guide](https://pyo3.rs/v" , env!("CARGO_PKG_VERSION" ), "/types.html#concrete-python-types)" )] |
31 | /// for an explanation of the different Python object types. |
32 | #[repr (transparent)] |
33 | pub struct PyAny(UnsafeCell<ffi::PyObject>); |
34 | |
35 | #[allow (non_snake_case)] |
36 | // Copied here as the macro does not accept deprecated functions. |
37 | // Originally ffi::object::PyObject_Check, but this is not in the Python C API. |
38 | fn PyObject_Check(_: *mut ffi::PyObject) -> c_int { |
39 | 1 |
40 | } |
41 | |
42 | pyobject_native_type_info!( |
43 | PyAny, |
44 | pyobject_native_static_type_object!(ffi::PyBaseObject_Type), |
45 | Some("builtins" ), |
46 | #checkfunction=PyObject_Check |
47 | ); |
48 | |
49 | pyobject_native_type_sized!(PyAny, ffi::PyObject); |
50 | // We cannot use `pyobject_subclassable_native_type!()` because it cfgs out on `Py_LIMITED_API`. |
51 | impl crate::impl_::pyclass::PyClassBaseType for PyAny { |
52 | type LayoutAsBase = crate::impl_::pycell::PyClassObjectBase<ffi::PyObject>; |
53 | type BaseNativeType = PyAny; |
54 | type Initializer = crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>; |
55 | type PyClassMutability = crate::pycell::impl_::ImmutableClass; |
56 | } |
57 | |
58 | /// This trait represents the Python APIs which are usable on all Python objects. |
59 | /// |
60 | /// It is recommended you import this trait via `use pyo3::prelude::*` rather than |
61 | /// by importing this trait directly. |
62 | #[doc (alias = "PyAny" )] |
63 | pub trait PyAnyMethods<'py>: crate::sealed::Sealed { |
64 | /// Returns whether `self` and `other` point to the same object. To compare |
65 | /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). |
66 | /// |
67 | /// This is equivalent to the Python expression `self is other`. |
68 | fn is<T: AsPyPointer>(&self, other: &T) -> bool; |
69 | |
70 | /// Determines whether this object has the given attribute. |
71 | /// |
72 | /// This is equivalent to the Python expression `hasattr(self, attr_name)`. |
73 | /// |
74 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
75 | /// to intern `attr_name`. |
76 | /// |
77 | /// # Example: `intern!`ing the attribute name |
78 | /// |
79 | /// ``` |
80 | /// # use pyo3::{prelude::*, intern}; |
81 | /// # |
82 | /// #[pyfunction] |
83 | /// fn has_version(sys: &Bound<'_, PyModule>) -> PyResult<bool> { |
84 | /// sys.hasattr(intern!(sys.py(), "version" )) |
85 | /// } |
86 | /// # |
87 | /// # Python::with_gil(|py| { |
88 | /// # let sys = py.import("sys" ).unwrap(); |
89 | /// # has_version(&sys).unwrap(); |
90 | /// # }); |
91 | /// ``` |
92 | fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> |
93 | where |
94 | N: IntoPyObject<'py, Target = PyString>; |
95 | |
96 | /// Retrieves an attribute value. |
97 | /// |
98 | /// This is equivalent to the Python expression `self.attr_name`. |
99 | /// |
100 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
101 | /// to intern `attr_name`. |
102 | /// |
103 | /// # Example: `intern!`ing the attribute name |
104 | /// |
105 | /// ``` |
106 | /// # use pyo3::{prelude::*, intern}; |
107 | /// # |
108 | /// #[pyfunction] |
109 | /// fn version<'py>(sys: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyAny>> { |
110 | /// sys.getattr(intern!(sys.py(), "version" )) |
111 | /// } |
112 | /// # |
113 | /// # Python::with_gil(|py| { |
114 | /// # let sys = py.import("sys" ).unwrap(); |
115 | /// # version(&sys).unwrap(); |
116 | /// # }); |
117 | /// ``` |
118 | fn getattr<N>(&self, attr_name: N) -> PyResult<Bound<'py, PyAny>> |
119 | where |
120 | N: IntoPyObject<'py, Target = PyString>; |
121 | |
122 | /// Retrieves an attribute value optionally. |
123 | /// |
124 | /// This is equivalent to the Python expression `getattr(self, attr_name, None)`, which may |
125 | /// be more efficient in some cases by simply returning `None` if the attribute is not found |
126 | /// instead of raising `AttributeError`. |
127 | /// |
128 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
129 | /// to intern `attr_name`. |
130 | /// |
131 | /// # Errors |
132 | /// Returns `Err` if an exception other than `AttributeError` is raised during attribute lookup, |
133 | /// such as a `ValueError` from a property or descriptor. |
134 | /// |
135 | /// # Example: Retrieving an optional attribute |
136 | /// ``` |
137 | /// # use pyo3::{prelude::*, intern}; |
138 | /// # |
139 | /// #[pyfunction] |
140 | /// fn get_version_if_exists<'py>(sys: &Bound<'py, PyModule>) -> PyResult<Option<Bound<'py, PyAny>>> { |
141 | /// sys.getattr_opt(intern!(sys.py(), "version" )) |
142 | /// } |
143 | /// # |
144 | /// # Python::with_gil(|py| { |
145 | /// # let sys = py.import("sys" ).unwrap(); |
146 | /// # let version = get_version_if_exists(&sys).unwrap(); |
147 | /// # assert!(version.is_some()); |
148 | /// # }); |
149 | /// ``` |
150 | fn getattr_opt<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>> |
151 | where |
152 | N: IntoPyObject<'py, Target = PyString>; |
153 | |
154 | /// Sets an attribute value. |
155 | /// |
156 | /// This is equivalent to the Python expression `self.attr_name = value`. |
157 | /// |
158 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
159 | /// to intern `name`. |
160 | /// |
161 | /// # Example: `intern!`ing the attribute name |
162 | /// |
163 | /// ``` |
164 | /// # use pyo3::{prelude::*, intern}; |
165 | /// # |
166 | /// #[pyfunction] |
167 | /// fn set_answer(ob: &Bound<'_, PyAny>) -> PyResult<()> { |
168 | /// ob.setattr(intern!(ob.py(), "answer" ), 42) |
169 | /// } |
170 | /// # |
171 | /// # Python::with_gil(|py| { |
172 | /// # let ob = PyModule::new(py, "empty" ).unwrap(); |
173 | /// # set_answer(&ob).unwrap(); |
174 | /// # }); |
175 | /// ``` |
176 | fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()> |
177 | where |
178 | N: IntoPyObject<'py, Target = PyString>, |
179 | V: IntoPyObject<'py>; |
180 | |
181 | /// Deletes an attribute. |
182 | /// |
183 | /// This is equivalent to the Python statement `del self.attr_name`. |
184 | /// |
185 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
186 | /// to intern `attr_name`. |
187 | fn delattr<N>(&self, attr_name: N) -> PyResult<()> |
188 | where |
189 | N: IntoPyObject<'py, Target = PyString>; |
190 | |
191 | /// Returns an [`Ordering`] between `self` and `other`. |
192 | /// |
193 | /// This is equivalent to the following Python code: |
194 | /// ```python |
195 | /// if self == other: |
196 | /// return Equal |
197 | /// elif a < b: |
198 | /// return Less |
199 | /// elif a > b: |
200 | /// return Greater |
201 | /// else: |
202 | /// raise TypeError("PyAny::compare(): All comparisons returned false") |
203 | /// ``` |
204 | /// |
205 | /// # Examples |
206 | /// |
207 | /// ```rust |
208 | /// use pyo3::prelude::*; |
209 | /// use pyo3::types::PyFloat; |
210 | /// use std::cmp::Ordering; |
211 | /// |
212 | /// # fn main() -> PyResult<()> { |
213 | /// Python::with_gil(|py| -> PyResult<()> { |
214 | /// let a = PyFloat::new(py, 0_f64); |
215 | /// let b = PyFloat::new(py, 42_f64); |
216 | /// assert_eq!(a.compare(b)?, Ordering::Less); |
217 | /// Ok(()) |
218 | /// })?; |
219 | /// # Ok(())} |
220 | /// ``` |
221 | /// |
222 | /// It will return `PyErr` for values that cannot be compared: |
223 | /// |
224 | /// ```rust |
225 | /// use pyo3::prelude::*; |
226 | /// use pyo3::types::{PyFloat, PyString}; |
227 | /// |
228 | /// # fn main() -> PyResult<()> { |
229 | /// Python::with_gil(|py| -> PyResult<()> { |
230 | /// let a = PyFloat::new(py, 0_f64); |
231 | /// let b = PyString::new(py, "zero" ); |
232 | /// assert!(a.compare(b).is_err()); |
233 | /// Ok(()) |
234 | /// })?; |
235 | /// # Ok(())} |
236 | /// ``` |
237 | fn compare<O>(&self, other: O) -> PyResult<Ordering> |
238 | where |
239 | O: IntoPyObject<'py>; |
240 | |
241 | /// Tests whether two Python objects obey a given [`CompareOp`]. |
242 | /// |
243 | /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne), |
244 | /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions |
245 | /// of this function. |
246 | /// |
247 | /// Depending on the value of `compare_op`, this is equivalent to one of the |
248 | /// following Python expressions: |
249 | /// |
250 | /// | `compare_op` | Python expression | |
251 | /// | :---: | :----: | |
252 | /// | [`CompareOp::Eq`] | `self == other` | |
253 | /// | [`CompareOp::Ne`] | `self != other` | |
254 | /// | [`CompareOp::Lt`] | `self < other` | |
255 | /// | [`CompareOp::Le`] | `self <= other` | |
256 | /// | [`CompareOp::Gt`] | `self > other` | |
257 | /// | [`CompareOp::Ge`] | `self >= other` | |
258 | /// |
259 | /// # Examples |
260 | /// |
261 | /// ```rust |
262 | /// use pyo3::class::basic::CompareOp; |
263 | /// use pyo3::prelude::*; |
264 | /// |
265 | /// # fn main() -> PyResult<()> { |
266 | /// Python::with_gil(|py| -> PyResult<()> { |
267 | /// let a = 0_u8.into_pyobject(py)?; |
268 | /// let b = 42_u8.into_pyobject(py)?; |
269 | /// assert!(a.rich_compare(b, CompareOp::Le)?.is_truthy()?); |
270 | /// Ok(()) |
271 | /// })?; |
272 | /// # Ok(())} |
273 | /// ``` |
274 | fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>> |
275 | where |
276 | O: IntoPyObject<'py>; |
277 | |
278 | /// Computes the negative of self. |
279 | /// |
280 | /// Equivalent to the Python expression `-self`. |
281 | fn neg(&self) -> PyResult<Bound<'py, PyAny>>; |
282 | |
283 | /// Computes the positive of self. |
284 | /// |
285 | /// Equivalent to the Python expression `+self`. |
286 | fn pos(&self) -> PyResult<Bound<'py, PyAny>>; |
287 | |
288 | /// Computes the absolute of self. |
289 | /// |
290 | /// Equivalent to the Python expression `abs(self)`. |
291 | fn abs(&self) -> PyResult<Bound<'py, PyAny>>; |
292 | |
293 | /// Computes `~self`. |
294 | fn bitnot(&self) -> PyResult<Bound<'py, PyAny>>; |
295 | |
296 | /// Tests whether this object is less than another. |
297 | /// |
298 | /// This is equivalent to the Python expression `self < other`. |
299 | fn lt<O>(&self, other: O) -> PyResult<bool> |
300 | where |
301 | O: IntoPyObject<'py>; |
302 | |
303 | /// Tests whether this object is less than or equal to another. |
304 | /// |
305 | /// This is equivalent to the Python expression `self <= other`. |
306 | fn le<O>(&self, other: O) -> PyResult<bool> |
307 | where |
308 | O: IntoPyObject<'py>; |
309 | |
310 | /// Tests whether this object is equal to another. |
311 | /// |
312 | /// This is equivalent to the Python expression `self == other`. |
313 | fn eq<O>(&self, other: O) -> PyResult<bool> |
314 | where |
315 | O: IntoPyObject<'py>; |
316 | |
317 | /// Tests whether this object is not equal to another. |
318 | /// |
319 | /// This is equivalent to the Python expression `self != other`. |
320 | fn ne<O>(&self, other: O) -> PyResult<bool> |
321 | where |
322 | O: IntoPyObject<'py>; |
323 | |
324 | /// Tests whether this object is greater than another. |
325 | /// |
326 | /// This is equivalent to the Python expression `self > other`. |
327 | fn gt<O>(&self, other: O) -> PyResult<bool> |
328 | where |
329 | O: IntoPyObject<'py>; |
330 | |
331 | /// Tests whether this object is greater than or equal to another. |
332 | /// |
333 | /// This is equivalent to the Python expression `self >= other`. |
334 | fn ge<O>(&self, other: O) -> PyResult<bool> |
335 | where |
336 | O: IntoPyObject<'py>; |
337 | |
338 | /// Computes `self + other`. |
339 | fn add<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
340 | where |
341 | O: IntoPyObject<'py>; |
342 | |
343 | /// Computes `self - other`. |
344 | fn sub<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
345 | where |
346 | O: IntoPyObject<'py>; |
347 | |
348 | /// Computes `self * other`. |
349 | fn mul<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
350 | where |
351 | O: IntoPyObject<'py>; |
352 | |
353 | /// Computes `self @ other`. |
354 | fn matmul<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
355 | where |
356 | O: IntoPyObject<'py>; |
357 | |
358 | /// Computes `self / other`. |
359 | fn div<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
360 | where |
361 | O: IntoPyObject<'py>; |
362 | |
363 | /// Computes `self // other`. |
364 | fn floor_div<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
365 | where |
366 | O: IntoPyObject<'py>; |
367 | |
368 | /// Computes `self % other`. |
369 | fn rem<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
370 | where |
371 | O: IntoPyObject<'py>; |
372 | |
373 | /// Computes `divmod(self, other)`. |
374 | fn divmod<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
375 | where |
376 | O: IntoPyObject<'py>; |
377 | |
378 | /// Computes `self << other`. |
379 | fn lshift<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
380 | where |
381 | O: IntoPyObject<'py>; |
382 | |
383 | /// Computes `self >> other`. |
384 | fn rshift<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
385 | where |
386 | O: IntoPyObject<'py>; |
387 | |
388 | /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). |
389 | /// `py.None()` may be passed for the `modulus`. |
390 | fn pow<O1, O2>(&self, other: O1, modulus: O2) -> PyResult<Bound<'py, PyAny>> |
391 | where |
392 | O1: IntoPyObject<'py>, |
393 | O2: IntoPyObject<'py>; |
394 | |
395 | /// Computes `self & other`. |
396 | fn bitand<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
397 | where |
398 | O: IntoPyObject<'py>; |
399 | |
400 | /// Computes `self | other`. |
401 | fn bitor<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
402 | where |
403 | O: IntoPyObject<'py>; |
404 | |
405 | /// Computes `self ^ other`. |
406 | fn bitxor<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
407 | where |
408 | O: IntoPyObject<'py>; |
409 | |
410 | /// Determines whether this object appears callable. |
411 | /// |
412 | /// This is equivalent to Python's [`callable()`][1] function. |
413 | /// |
414 | /// # Examples |
415 | /// |
416 | /// ```rust |
417 | /// use pyo3::prelude::*; |
418 | /// |
419 | /// # fn main() -> PyResult<()> { |
420 | /// Python::with_gil(|py| -> PyResult<()> { |
421 | /// let builtins = PyModule::import(py, "builtins" )?; |
422 | /// let print = builtins.getattr("print" )?; |
423 | /// assert!(print.is_callable()); |
424 | /// Ok(()) |
425 | /// })?; |
426 | /// # Ok(())} |
427 | /// ``` |
428 | /// |
429 | /// This is equivalent to the Python statement `assert callable(print)`. |
430 | /// |
431 | /// Note that unless an API needs to distinguish between callable and |
432 | /// non-callable objects, there is no point in checking for callability. |
433 | /// Instead, it is better to just do the call and handle potential |
434 | /// exceptions. |
435 | /// |
436 | /// [1]: https://docs.python.org/3/library/functions.html#callable |
437 | fn is_callable(&self) -> bool; |
438 | |
439 | /// Calls the object. |
440 | /// |
441 | /// This is equivalent to the Python expression `self(*args, **kwargs)`. |
442 | /// |
443 | /// # Examples |
444 | /// |
445 | /// ```rust |
446 | /// use pyo3::prelude::*; |
447 | /// use pyo3::types::PyDict; |
448 | /// use pyo3_ffi::c_str; |
449 | /// use std::ffi::CStr; |
450 | /// |
451 | /// const CODE: &CStr = c_str!(r#" |
452 | /// def function(*args, **kwargs): |
453 | /// assert args == ("hello",) |
454 | /// assert kwargs == {"cruel": "world"} |
455 | /// return "called with args and kwargs" |
456 | /// "# ); |
457 | /// |
458 | /// # fn main() -> PyResult<()> { |
459 | /// Python::with_gil(|py| { |
460 | /// let module = PyModule::from_code(py, CODE, c_str!("" ), c_str!("" ))?; |
461 | /// let fun = module.getattr("function" )?; |
462 | /// let args = ("hello" ,); |
463 | /// let kwargs = PyDict::new(py); |
464 | /// kwargs.set_item("cruel" , "world" )?; |
465 | /// let result = fun.call(args, Some(&kwargs))?; |
466 | /// assert_eq!(result.extract::<String>()?, "called with args and kwargs" ); |
467 | /// Ok(()) |
468 | /// }) |
469 | /// # } |
470 | /// ``` |
471 | fn call<A>(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult<Bound<'py, PyAny>> |
472 | where |
473 | A: PyCallArgs<'py>; |
474 | |
475 | /// Calls the object without arguments. |
476 | /// |
477 | /// This is equivalent to the Python expression `self()`. |
478 | /// |
479 | /// # Examples |
480 | /// |
481 | /// ```no_run |
482 | /// use pyo3::prelude::*; |
483 | /// |
484 | /// # fn main() -> PyResult<()> { |
485 | /// Python::with_gil(|py| -> PyResult<()> { |
486 | /// let module = PyModule::import(py, "builtins" )?; |
487 | /// let help = module.getattr("help" )?; |
488 | /// help.call0()?; |
489 | /// Ok(()) |
490 | /// })?; |
491 | /// # Ok(())} |
492 | /// ``` |
493 | /// |
494 | /// This is equivalent to the Python expression `help()`. |
495 | fn call0(&self) -> PyResult<Bound<'py, PyAny>>; |
496 | |
497 | /// Calls the object with only positional arguments. |
498 | /// |
499 | /// This is equivalent to the Python expression `self(*args)`. |
500 | /// |
501 | /// # Examples |
502 | /// |
503 | /// ```rust |
504 | /// use pyo3::prelude::*; |
505 | /// use pyo3_ffi::c_str; |
506 | /// use std::ffi::CStr; |
507 | /// |
508 | /// const CODE: &CStr = c_str!(r#" |
509 | /// def function(*args, **kwargs): |
510 | /// assert args == ("hello",) |
511 | /// assert kwargs == {} |
512 | /// return "called with args" |
513 | /// "# ); |
514 | /// |
515 | /// # fn main() -> PyResult<()> { |
516 | /// Python::with_gil(|py| { |
517 | /// let module = PyModule::from_code(py, CODE, c_str!("" ), c_str!("" ))?; |
518 | /// let fun = module.getattr("function" )?; |
519 | /// let args = ("hello" ,); |
520 | /// let result = fun.call1(args)?; |
521 | /// assert_eq!(result.extract::<String>()?, "called with args" ); |
522 | /// Ok(()) |
523 | /// }) |
524 | /// # } |
525 | /// ``` |
526 | fn call1<A>(&self, args: A) -> PyResult<Bound<'py, PyAny>> |
527 | where |
528 | A: PyCallArgs<'py>; |
529 | |
530 | /// Calls a method on the object. |
531 | /// |
532 | /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. |
533 | /// |
534 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
535 | /// to intern `name`. |
536 | /// |
537 | /// # Examples |
538 | /// |
539 | /// ```rust |
540 | /// use pyo3::prelude::*; |
541 | /// use pyo3::types::PyDict; |
542 | /// use pyo3_ffi::c_str; |
543 | /// use std::ffi::CStr; |
544 | /// |
545 | /// const CODE: &CStr = c_str!(r#" |
546 | /// class A: |
547 | /// def method(self, *args, **kwargs): |
548 | /// assert args == ("hello",) |
549 | /// assert kwargs == {"cruel": "world"} |
550 | /// return "called with args and kwargs" |
551 | /// a = A() |
552 | /// "# ); |
553 | /// |
554 | /// # fn main() -> PyResult<()> { |
555 | /// Python::with_gil(|py| { |
556 | /// let module = PyModule::from_code(py, CODE, c_str!("" ), c_str!("" ))?; |
557 | /// let instance = module.getattr("a" )?; |
558 | /// let args = ("hello" ,); |
559 | /// let kwargs = PyDict::new(py); |
560 | /// kwargs.set_item("cruel" , "world" )?; |
561 | /// let result = instance.call_method("method" , args, Some(&kwargs))?; |
562 | /// assert_eq!(result.extract::<String>()?, "called with args and kwargs" ); |
563 | /// Ok(()) |
564 | /// }) |
565 | /// # } |
566 | /// ``` |
567 | fn call_method<N, A>( |
568 | &self, |
569 | name: N, |
570 | args: A, |
571 | kwargs: Option<&Bound<'py, PyDict>>, |
572 | ) -> PyResult<Bound<'py, PyAny>> |
573 | where |
574 | N: IntoPyObject<'py, Target = PyString>, |
575 | A: PyCallArgs<'py>; |
576 | |
577 | /// Calls a method on the object without arguments. |
578 | /// |
579 | /// This is equivalent to the Python expression `self.name()`. |
580 | /// |
581 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
582 | /// to intern `name`. |
583 | /// |
584 | /// # Examples |
585 | /// |
586 | /// ```rust |
587 | /// use pyo3::prelude::*; |
588 | /// use pyo3_ffi::c_str; |
589 | /// use std::ffi::CStr; |
590 | /// |
591 | /// const CODE: &CStr = c_str!(r#" |
592 | /// class A: |
593 | /// def method(self, *args, **kwargs): |
594 | /// assert args == () |
595 | /// assert kwargs == {} |
596 | /// return "called with no arguments" |
597 | /// a = A() |
598 | /// "# ); |
599 | /// |
600 | /// # fn main() -> PyResult<()> { |
601 | /// Python::with_gil(|py| { |
602 | /// let module = PyModule::from_code(py, CODE, c_str!("" ), c_str!("" ))?; |
603 | /// let instance = module.getattr("a" )?; |
604 | /// let result = instance.call_method0("method" )?; |
605 | /// assert_eq!(result.extract::<String>()?, "called with no arguments" ); |
606 | /// Ok(()) |
607 | /// }) |
608 | /// # } |
609 | /// ``` |
610 | fn call_method0<N>(&self, name: N) -> PyResult<Bound<'py, PyAny>> |
611 | where |
612 | N: IntoPyObject<'py, Target = PyString>; |
613 | |
614 | /// Calls a method on the object with only positional arguments. |
615 | /// |
616 | /// This is equivalent to the Python expression `self.name(*args)`. |
617 | /// |
618 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
619 | /// to intern `name`. |
620 | /// |
621 | /// # Examples |
622 | /// |
623 | /// ```rust |
624 | /// use pyo3::prelude::*; |
625 | /// use pyo3_ffi::c_str; |
626 | /// use std::ffi::CStr; |
627 | /// |
628 | /// const CODE: &CStr = c_str!(r#" |
629 | /// class A: |
630 | /// def method(self, *args, **kwargs): |
631 | /// assert args == ("hello",) |
632 | /// assert kwargs == {} |
633 | /// return "called with args" |
634 | /// a = A() |
635 | /// "# ); |
636 | /// |
637 | /// # fn main() -> PyResult<()> { |
638 | /// Python::with_gil(|py| { |
639 | /// let module = PyModule::from_code(py, CODE, c_str!("" ), c_str!("" ))?; |
640 | /// let instance = module.getattr("a" )?; |
641 | /// let args = ("hello" ,); |
642 | /// let result = instance.call_method1("method" , args)?; |
643 | /// assert_eq!(result.extract::<String>()?, "called with args" ); |
644 | /// Ok(()) |
645 | /// }) |
646 | /// # } |
647 | /// ``` |
648 | fn call_method1<N, A>(&self, name: N, args: A) -> PyResult<Bound<'py, PyAny>> |
649 | where |
650 | N: IntoPyObject<'py, Target = PyString>, |
651 | A: PyCallArgs<'py>; |
652 | |
653 | /// Returns whether the object is considered to be true. |
654 | /// |
655 | /// This is equivalent to the Python expression `bool(self)`. |
656 | fn is_truthy(&self) -> PyResult<bool>; |
657 | |
658 | /// Returns whether the object is considered to be None. |
659 | /// |
660 | /// This is equivalent to the Python expression `self is None`. |
661 | fn is_none(&self) -> bool; |
662 | |
663 | /// Returns whether the object is Ellipsis, e.g. `...`. |
664 | /// |
665 | /// This is equivalent to the Python expression `self is ...`. |
666 | #[deprecated (since = "0.23.0" , note = "use `.is(py.Ellipsis())` instead" )] |
667 | fn is_ellipsis(&self) -> bool; |
668 | |
669 | /// Returns true if the sequence or mapping has a length of 0. |
670 | /// |
671 | /// This is equivalent to the Python expression `len(self) == 0`. |
672 | fn is_empty(&self) -> PyResult<bool>; |
673 | |
674 | /// Gets an item from the collection. |
675 | /// |
676 | /// This is equivalent to the Python expression `self[key]`. |
677 | fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>> |
678 | where |
679 | K: IntoPyObject<'py>; |
680 | |
681 | /// Sets a collection item value. |
682 | /// |
683 | /// This is equivalent to the Python expression `self[key] = value`. |
684 | fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()> |
685 | where |
686 | K: IntoPyObject<'py>, |
687 | V: IntoPyObject<'py>; |
688 | |
689 | /// Deletes an item from the collection. |
690 | /// |
691 | /// This is equivalent to the Python expression `del self[key]`. |
692 | fn del_item<K>(&self, key: K) -> PyResult<()> |
693 | where |
694 | K: IntoPyObject<'py>; |
695 | |
696 | /// Takes an object and returns an iterator for it. Returns an error if the object is not |
697 | /// iterable. |
698 | /// |
699 | /// This is typically a new iterator but if the argument is an iterator, |
700 | /// this returns itself. |
701 | /// |
702 | /// # Example: Checking a Python object for iterability |
703 | /// |
704 | /// ```rust |
705 | /// use pyo3::prelude::*; |
706 | /// use pyo3::types::{PyAny, PyNone}; |
707 | /// |
708 | /// fn is_iterable(obj: &Bound<'_, PyAny>) -> bool { |
709 | /// match obj.try_iter() { |
710 | /// Ok(_) => true, |
711 | /// Err(_) => false, |
712 | /// } |
713 | /// } |
714 | /// |
715 | /// Python::with_gil(|py| { |
716 | /// assert!(is_iterable(&vec![1, 2, 3].into_pyobject(py).unwrap())); |
717 | /// assert!(!is_iterable(&PyNone::get(py))); |
718 | /// }); |
719 | /// ``` |
720 | fn try_iter(&self) -> PyResult<Bound<'py, PyIterator>>; |
721 | |
722 | /// Takes an object and returns an iterator for it. |
723 | /// |
724 | /// This is typically a new iterator but if the argument is an iterator, |
725 | /// this returns itself. |
726 | #[deprecated (since = "0.23.0" , note = "use `try_iter` instead" )] |
727 | fn iter(&self) -> PyResult<Bound<'py, PyIterator>>; |
728 | |
729 | /// Returns the Python type object for this object's type. |
730 | fn get_type(&self) -> Bound<'py, PyType>; |
731 | |
732 | /// Returns the Python type pointer for this object. |
733 | fn get_type_ptr(&self) -> *mut ffi::PyTypeObject; |
734 | |
735 | /// Downcast this `PyAny` to a concrete Python type or pyclass. |
736 | /// |
737 | /// Note that you can often avoid downcasting yourself by just specifying |
738 | /// the desired type in function or method signatures. |
739 | /// However, manual downcasting is sometimes necessary. |
740 | /// |
741 | /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). |
742 | /// |
743 | /// # Example: Downcasting to a specific Python object |
744 | /// |
745 | /// ```rust |
746 | /// use pyo3::prelude::*; |
747 | /// use pyo3::types::{PyDict, PyList}; |
748 | /// |
749 | /// Python::with_gil(|py| { |
750 | /// let dict = PyDict::new(py); |
751 | /// assert!(dict.is_instance_of::<PyAny>()); |
752 | /// let any = dict.as_any(); |
753 | /// |
754 | /// assert!(any.downcast::<PyDict>().is_ok()); |
755 | /// assert!(any.downcast::<PyList>().is_err()); |
756 | /// }); |
757 | /// ``` |
758 | /// |
759 | /// # Example: Getting a reference to a pyclass |
760 | /// |
761 | /// This is useful if you want to mutate a `PyObject` that |
762 | /// might actually be a pyclass. |
763 | /// |
764 | /// ```rust |
765 | /// # fn main() -> Result<(), pyo3::PyErr> { |
766 | /// use pyo3::prelude::*; |
767 | /// |
768 | /// #[pyclass] |
769 | /// struct Class { |
770 | /// i: i32, |
771 | /// } |
772 | /// |
773 | /// Python::with_gil(|py| { |
774 | /// let class = Py::new(py, Class { i: 0 }).unwrap().into_bound(py).into_any(); |
775 | /// |
776 | /// let class_bound: &Bound<'_, Class> = class.downcast()?; |
777 | /// |
778 | /// class_bound.borrow_mut().i += 1; |
779 | /// |
780 | /// // Alternatively you can get a `PyRefMut` directly |
781 | /// let class_ref: PyRefMut<'_, Class> = class.extract()?; |
782 | /// assert_eq!(class_ref.i, 1); |
783 | /// Ok(()) |
784 | /// }) |
785 | /// # } |
786 | /// ``` |
787 | fn downcast<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> |
788 | where |
789 | T: PyTypeCheck; |
790 | |
791 | /// Like `downcast` but takes ownership of `self`. |
792 | /// |
793 | /// In case of an error, it is possible to retrieve `self` again via [`DowncastIntoError::into_inner`]. |
794 | /// |
795 | /// # Example |
796 | /// |
797 | /// ```rust |
798 | /// use pyo3::prelude::*; |
799 | /// use pyo3::types::{PyDict, PyList}; |
800 | /// |
801 | /// Python::with_gil(|py| { |
802 | /// let obj: Bound<'_, PyAny> = PyDict::new(py).into_any(); |
803 | /// |
804 | /// let obj: Bound<'_, PyAny> = match obj.downcast_into::<PyList>() { |
805 | /// Ok(_) => panic!("obj should not be a list" ), |
806 | /// Err(err) => err.into_inner(), |
807 | /// }; |
808 | /// |
809 | /// // obj is a dictionary |
810 | /// assert!(obj.downcast_into::<PyDict>().is_ok()); |
811 | /// }) |
812 | /// ``` |
813 | fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>> |
814 | where |
815 | T: PyTypeCheck; |
816 | |
817 | /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it). |
818 | /// |
819 | /// It is almost always better to use [`PyAnyMethods::downcast`] because it accounts for Python |
820 | /// subtyping. Use this method only when you do not want to allow subtypes. |
821 | /// |
822 | /// The advantage of this method over [`PyAnyMethods::downcast`] is that it is faster. The implementation |
823 | /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas |
824 | /// `downcast` uses `isinstance(self, T)`. |
825 | /// |
826 | /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). |
827 | /// |
828 | /// # Example: Downcasting to a specific Python object but not a subtype |
829 | /// |
830 | /// ```rust |
831 | /// use pyo3::prelude::*; |
832 | /// use pyo3::types::{PyBool, PyInt}; |
833 | /// |
834 | /// Python::with_gil(|py| { |
835 | /// let b = PyBool::new(py, true); |
836 | /// assert!(b.is_instance_of::<PyBool>()); |
837 | /// let any: &Bound<'_, PyAny> = b.as_any(); |
838 | /// |
839 | /// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int` |
840 | /// // but `downcast_exact` will not. |
841 | /// assert!(any.downcast::<PyInt>().is_ok()); |
842 | /// assert!(any.downcast_exact::<PyInt>().is_err()); |
843 | /// |
844 | /// assert!(any.downcast_exact::<PyBool>().is_ok()); |
845 | /// }); |
846 | /// ``` |
847 | fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> |
848 | where |
849 | T: PyTypeInfo; |
850 | |
851 | /// Like `downcast_exact` but takes ownership of `self`. |
852 | fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>> |
853 | where |
854 | T: PyTypeInfo; |
855 | |
856 | /// Converts this `PyAny` to a concrete Python type without checking validity. |
857 | /// |
858 | /// # Safety |
859 | /// |
860 | /// Callers must ensure that the type is valid or risk type confusion. |
861 | unsafe fn downcast_unchecked<T>(&self) -> &Bound<'py, T>; |
862 | |
863 | /// Like `downcast_unchecked` but takes ownership of `self`. |
864 | /// |
865 | /// # Safety |
866 | /// |
867 | /// Callers must ensure that the type is valid or risk type confusion. |
868 | unsafe fn downcast_into_unchecked<T>(self) -> Bound<'py, T>; |
869 | |
870 | /// Extracts some type from the Python object. |
871 | /// |
872 | /// This is a wrapper function around |
873 | /// [`FromPyObject::extract_bound()`](crate::FromPyObject::extract_bound). |
874 | fn extract<'a, T>(&'a self) -> PyResult<T> |
875 | where |
876 | T: FromPyObjectBound<'a, 'py>; |
877 | |
878 | /// Returns the reference count for the Python object. |
879 | fn get_refcnt(&self) -> isize; |
880 | |
881 | /// Computes the "repr" representation of self. |
882 | /// |
883 | /// This is equivalent to the Python expression `repr(self)`. |
884 | fn repr(&self) -> PyResult<Bound<'py, PyString>>; |
885 | |
886 | /// Computes the "str" representation of self. |
887 | /// |
888 | /// This is equivalent to the Python expression `str(self)`. |
889 | fn str(&self) -> PyResult<Bound<'py, PyString>>; |
890 | |
891 | /// Retrieves the hash code of self. |
892 | /// |
893 | /// This is equivalent to the Python expression `hash(self)`. |
894 | fn hash(&self) -> PyResult<isize>; |
895 | |
896 | /// Returns the length of the sequence or mapping. |
897 | /// |
898 | /// This is equivalent to the Python expression `len(self)`. |
899 | fn len(&self) -> PyResult<usize>; |
900 | |
901 | /// Returns the list of attributes of this object. |
902 | /// |
903 | /// This is equivalent to the Python expression `dir(self)`. |
904 | fn dir(&self) -> PyResult<Bound<'py, PyList>>; |
905 | |
906 | /// Checks whether this object is an instance of type `ty`. |
907 | /// |
908 | /// This is equivalent to the Python expression `isinstance(self, ty)`. |
909 | fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult<bool>; |
910 | |
911 | /// Checks whether this object is an instance of exactly type `ty` (not a subclass). |
912 | /// |
913 | /// This is equivalent to the Python expression `type(self) is ty`. |
914 | fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool; |
915 | |
916 | /// Checks whether this object is an instance of type `T`. |
917 | /// |
918 | /// This is equivalent to the Python expression `isinstance(self, T)`, |
919 | /// if the type `T` is known at compile time. |
920 | fn is_instance_of<T: PyTypeInfo>(&self) -> bool; |
921 | |
922 | /// Checks whether this object is an instance of exactly type `T`. |
923 | /// |
924 | /// This is equivalent to the Python expression `type(self) is T`, |
925 | /// if the type `T` is known at compile time. |
926 | fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool; |
927 | |
928 | /// Determines if self contains `value`. |
929 | /// |
930 | /// This is equivalent to the Python expression `value in self`. |
931 | fn contains<V>(&self, value: V) -> PyResult<bool> |
932 | where |
933 | V: IntoPyObject<'py>; |
934 | |
935 | /// Return a proxy object that delegates method calls to a parent or sibling class of type. |
936 | /// |
937 | /// This is equivalent to the Python expression `super()` |
938 | #[cfg (not(any(PyPy, GraalPy)))] |
939 | fn py_super(&self) -> PyResult<Bound<'py, PySuper>>; |
940 | } |
941 | |
942 | macro_rules! implement_binop { |
943 | ($name:ident, $c_api:ident, $op:expr) => { |
944 | #[doc = concat!("Computes `self " , $op, " other`." )] |
945 | fn $name<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
946 | where |
947 | O: IntoPyObject<'py>, |
948 | { |
949 | fn inner<'py>( |
950 | any: &Bound<'py, PyAny>, |
951 | other: Borrowed<'_, 'py, PyAny>, |
952 | ) -> PyResult<Bound<'py, PyAny>> { |
953 | unsafe { ffi::$c_api(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) } |
954 | } |
955 | |
956 | let py = self.py(); |
957 | inner( |
958 | self, |
959 | other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
960 | ) |
961 | } |
962 | }; |
963 | } |
964 | |
965 | impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { |
966 | #[inline ] |
967 | fn is<T: AsPyPointer>(&self, other: &T) -> bool { |
968 | ptr::eq(self.as_ptr(), other.as_ptr()) |
969 | } |
970 | |
971 | fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> |
972 | where |
973 | N: IntoPyObject<'py, Target = PyString>, |
974 | { |
975 | // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2. |
976 | // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3. |
977 | fn inner(py: Python<'_>, getattr_result: PyResult<Bound<'_, PyAny>>) -> PyResult<bool> { |
978 | match getattr_result { |
979 | Ok(_) => Ok(true), |
980 | Err(err) if err.is_instance_of::<PyAttributeError>(py) => Ok(false), |
981 | Err(e) => Err(e), |
982 | } |
983 | } |
984 | |
985 | inner(self.py(), self.getattr(attr_name)) |
986 | } |
987 | |
988 | fn getattr<N>(&self, attr_name: N) -> PyResult<Bound<'py, PyAny>> |
989 | where |
990 | N: IntoPyObject<'py, Target = PyString>, |
991 | { |
992 | fn inner<'py>( |
993 | any: &Bound<'py, PyAny>, |
994 | attr_name: Borrowed<'_, '_, PyString>, |
995 | ) -> PyResult<Bound<'py, PyAny>> { |
996 | unsafe { |
997 | ffi::PyObject_GetAttr(any.as_ptr(), attr_name.as_ptr()) |
998 | .assume_owned_or_err(any.py()) |
999 | } |
1000 | } |
1001 | |
1002 | inner( |
1003 | self, |
1004 | attr_name |
1005 | .into_pyobject(self.py()) |
1006 | .map_err(Into::into)? |
1007 | .as_borrowed(), |
1008 | ) |
1009 | } |
1010 | |
1011 | fn getattr_opt<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>> |
1012 | where |
1013 | N: IntoPyObject<'py, Target = PyString>, |
1014 | { |
1015 | fn inner<'py>( |
1016 | any: &Bound<'py, PyAny>, |
1017 | attr_name: Borrowed<'_, 'py, PyString>, |
1018 | ) -> PyResult<Option<Bound<'py, PyAny>>> { |
1019 | #[cfg (Py_3_13)] |
1020 | { |
1021 | let mut resp_ptr: *mut ffi::PyObject = std::ptr::null_mut(); |
1022 | match unsafe { |
1023 | ffi::PyObject_GetOptionalAttr(any.as_ptr(), attr_name.as_ptr(), &mut resp_ptr) |
1024 | } { |
1025 | // Attribute found, result is a new strong reference |
1026 | 1 => { |
1027 | let bound = unsafe { Bound::from_owned_ptr(any.py(), resp_ptr) }; |
1028 | Ok(Some(bound)) |
1029 | } |
1030 | // Attribute not found, result is NULL |
1031 | 0 => Ok(None), |
1032 | |
1033 | // An error occurred (other than AttributeError) |
1034 | _ => Err(PyErr::fetch(any.py())), |
1035 | } |
1036 | } |
1037 | |
1038 | #[cfg (not(Py_3_13))] |
1039 | { |
1040 | match any.getattr(attr_name) { |
1041 | Ok(bound) => Ok(Some(bound)), |
1042 | Err(err) => { |
1043 | let err_type = err |
1044 | .get_type(any.py()) |
1045 | .is(&PyType::new::<PyAttributeError>(any.py())); |
1046 | match err_type { |
1047 | true => Ok(None), |
1048 | false => Err(err), |
1049 | } |
1050 | } |
1051 | } |
1052 | } |
1053 | } |
1054 | |
1055 | let py = self.py(); |
1056 | inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed()) |
1057 | } |
1058 | |
1059 | fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()> |
1060 | where |
1061 | N: IntoPyObject<'py, Target = PyString>, |
1062 | V: IntoPyObject<'py>, |
1063 | { |
1064 | fn inner( |
1065 | any: &Bound<'_, PyAny>, |
1066 | attr_name: Borrowed<'_, '_, PyString>, |
1067 | value: Borrowed<'_, '_, PyAny>, |
1068 | ) -> PyResult<()> { |
1069 | err::error_on_minusone(any.py(), unsafe { |
1070 | ffi::PyObject_SetAttr(any.as_ptr(), attr_name.as_ptr(), value.as_ptr()) |
1071 | }) |
1072 | } |
1073 | |
1074 | let py = self.py(); |
1075 | inner( |
1076 | self, |
1077 | attr_name.into_pyobject_or_pyerr(py)?.as_borrowed(), |
1078 | value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1079 | ) |
1080 | } |
1081 | |
1082 | fn delattr<N>(&self, attr_name: N) -> PyResult<()> |
1083 | where |
1084 | N: IntoPyObject<'py, Target = PyString>, |
1085 | { |
1086 | fn inner(any: &Bound<'_, PyAny>, attr_name: Borrowed<'_, '_, PyString>) -> PyResult<()> { |
1087 | err::error_on_minusone(any.py(), unsafe { |
1088 | ffi::PyObject_DelAttr(any.as_ptr(), attr_name.as_ptr()) |
1089 | }) |
1090 | } |
1091 | |
1092 | let py = self.py(); |
1093 | inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed()) |
1094 | } |
1095 | |
1096 | fn compare<O>(&self, other: O) -> PyResult<Ordering> |
1097 | where |
1098 | O: IntoPyObject<'py>, |
1099 | { |
1100 | fn inner(any: &Bound<'_, PyAny>, other: Borrowed<'_, '_, PyAny>) -> PyResult<Ordering> { |
1101 | let other = other.as_ptr(); |
1102 | // Almost the same as ffi::PyObject_RichCompareBool, but this one doesn't try self == other. |
1103 | // See https://github.com/PyO3/pyo3/issues/985 for more. |
1104 | let do_compare = |other, op| unsafe { |
1105 | ffi::PyObject_RichCompare(any.as_ptr(), other, op) |
1106 | .assume_owned_or_err(any.py()) |
1107 | .and_then(|obj| obj.is_truthy()) |
1108 | }; |
1109 | if do_compare(other, ffi::Py_EQ)? { |
1110 | Ok(Ordering::Equal) |
1111 | } else if do_compare(other, ffi::Py_LT)? { |
1112 | Ok(Ordering::Less) |
1113 | } else if do_compare(other, ffi::Py_GT)? { |
1114 | Ok(Ordering::Greater) |
1115 | } else { |
1116 | Err(PyTypeError::new_err( |
1117 | "PyAny::compare(): All comparisons returned false" , |
1118 | )) |
1119 | } |
1120 | } |
1121 | |
1122 | let py = self.py(); |
1123 | inner( |
1124 | self, |
1125 | other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1126 | ) |
1127 | } |
1128 | |
1129 | fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>> |
1130 | where |
1131 | O: IntoPyObject<'py>, |
1132 | { |
1133 | fn inner<'py>( |
1134 | any: &Bound<'py, PyAny>, |
1135 | other: Borrowed<'_, 'py, PyAny>, |
1136 | compare_op: CompareOp, |
1137 | ) -> PyResult<Bound<'py, PyAny>> { |
1138 | unsafe { |
1139 | ffi::PyObject_RichCompare(any.as_ptr(), other.as_ptr(), compare_op as c_int) |
1140 | .assume_owned_or_err(any.py()) |
1141 | } |
1142 | } |
1143 | |
1144 | let py = self.py(); |
1145 | inner( |
1146 | self, |
1147 | other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1148 | compare_op, |
1149 | ) |
1150 | } |
1151 | |
1152 | fn neg(&self) -> PyResult<Bound<'py, PyAny>> { |
1153 | unsafe { ffi::PyNumber_Negative(self.as_ptr()).assume_owned_or_err(self.py()) } |
1154 | } |
1155 | |
1156 | fn pos(&self) -> PyResult<Bound<'py, PyAny>> { |
1157 | fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> { |
1158 | unsafe { ffi::PyNumber_Positive(any.as_ptr()).assume_owned_or_err(any.py()) } |
1159 | } |
1160 | |
1161 | inner(self) |
1162 | } |
1163 | |
1164 | fn abs(&self) -> PyResult<Bound<'py, PyAny>> { |
1165 | fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> { |
1166 | unsafe { ffi::PyNumber_Absolute(any.as_ptr()).assume_owned_or_err(any.py()) } |
1167 | } |
1168 | |
1169 | inner(self) |
1170 | } |
1171 | |
1172 | fn bitnot(&self) -> PyResult<Bound<'py, PyAny>> { |
1173 | fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> { |
1174 | unsafe { ffi::PyNumber_Invert(any.as_ptr()).assume_owned_or_err(any.py()) } |
1175 | } |
1176 | |
1177 | inner(self) |
1178 | } |
1179 | |
1180 | fn lt<O>(&self, other: O) -> PyResult<bool> |
1181 | where |
1182 | O: IntoPyObject<'py>, |
1183 | { |
1184 | self.rich_compare(other, CompareOp::Lt) |
1185 | .and_then(|any| any.is_truthy()) |
1186 | } |
1187 | |
1188 | fn le<O>(&self, other: O) -> PyResult<bool> |
1189 | where |
1190 | O: IntoPyObject<'py>, |
1191 | { |
1192 | self.rich_compare(other, CompareOp::Le) |
1193 | .and_then(|any| any.is_truthy()) |
1194 | } |
1195 | |
1196 | fn eq<O>(&self, other: O) -> PyResult<bool> |
1197 | where |
1198 | O: IntoPyObject<'py>, |
1199 | { |
1200 | self.rich_compare(other, CompareOp::Eq) |
1201 | .and_then(|any| any.is_truthy()) |
1202 | } |
1203 | |
1204 | fn ne<O>(&self, other: O) -> PyResult<bool> |
1205 | where |
1206 | O: IntoPyObject<'py>, |
1207 | { |
1208 | self.rich_compare(other, CompareOp::Ne) |
1209 | .and_then(|any| any.is_truthy()) |
1210 | } |
1211 | |
1212 | fn gt<O>(&self, other: O) -> PyResult<bool> |
1213 | where |
1214 | O: IntoPyObject<'py>, |
1215 | { |
1216 | self.rich_compare(other, CompareOp::Gt) |
1217 | .and_then(|any| any.is_truthy()) |
1218 | } |
1219 | |
1220 | fn ge<O>(&self, other: O) -> PyResult<bool> |
1221 | where |
1222 | O: IntoPyObject<'py>, |
1223 | { |
1224 | self.rich_compare(other, CompareOp::Ge) |
1225 | .and_then(|any| any.is_truthy()) |
1226 | } |
1227 | |
1228 | implement_binop!(add, PyNumber_Add, "+" ); |
1229 | implement_binop!(sub, PyNumber_Subtract, "-" ); |
1230 | implement_binop!(mul, PyNumber_Multiply, "*" ); |
1231 | implement_binop!(matmul, PyNumber_MatrixMultiply, "@" ); |
1232 | implement_binop!(div, PyNumber_TrueDivide, "/" ); |
1233 | implement_binop!(floor_div, PyNumber_FloorDivide, "//" ); |
1234 | implement_binop!(rem, PyNumber_Remainder, "%" ); |
1235 | implement_binop!(lshift, PyNumber_Lshift, "<<" ); |
1236 | implement_binop!(rshift, PyNumber_Rshift, ">>" ); |
1237 | implement_binop!(bitand, PyNumber_And, "&" ); |
1238 | implement_binop!(bitor, PyNumber_Or, "|" ); |
1239 | implement_binop!(bitxor, PyNumber_Xor, "^" ); |
1240 | |
1241 | /// Computes `divmod(self, other)`. |
1242 | fn divmod<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>> |
1243 | where |
1244 | O: IntoPyObject<'py>, |
1245 | { |
1246 | fn inner<'py>( |
1247 | any: &Bound<'py, PyAny>, |
1248 | other: Borrowed<'_, 'py, PyAny>, |
1249 | ) -> PyResult<Bound<'py, PyAny>> { |
1250 | unsafe { |
1251 | ffi::PyNumber_Divmod(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) |
1252 | } |
1253 | } |
1254 | |
1255 | let py = self.py(); |
1256 | inner( |
1257 | self, |
1258 | other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1259 | ) |
1260 | } |
1261 | |
1262 | /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). |
1263 | /// `py.None()` may be passed for the `modulus`. |
1264 | fn pow<O1, O2>(&self, other: O1, modulus: O2) -> PyResult<Bound<'py, PyAny>> |
1265 | where |
1266 | O1: IntoPyObject<'py>, |
1267 | O2: IntoPyObject<'py>, |
1268 | { |
1269 | fn inner<'py>( |
1270 | any: &Bound<'py, PyAny>, |
1271 | other: Borrowed<'_, 'py, PyAny>, |
1272 | modulus: Borrowed<'_, 'py, PyAny>, |
1273 | ) -> PyResult<Bound<'py, PyAny>> { |
1274 | unsafe { |
1275 | ffi::PyNumber_Power(any.as_ptr(), other.as_ptr(), modulus.as_ptr()) |
1276 | .assume_owned_or_err(any.py()) |
1277 | } |
1278 | } |
1279 | |
1280 | let py = self.py(); |
1281 | inner( |
1282 | self, |
1283 | other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1284 | modulus.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1285 | ) |
1286 | } |
1287 | |
1288 | fn is_callable(&self) -> bool { |
1289 | unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 } |
1290 | } |
1291 | |
1292 | fn call<A>(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult<Bound<'py, PyAny>> |
1293 | where |
1294 | A: PyCallArgs<'py>, |
1295 | { |
1296 | if let Some(kwargs) = kwargs { |
1297 | args.call( |
1298 | self.as_borrowed(), |
1299 | kwargs.as_borrowed(), |
1300 | crate::call::private::Token, |
1301 | ) |
1302 | } else { |
1303 | args.call_positional(self.as_borrowed(), crate::call::private::Token) |
1304 | } |
1305 | } |
1306 | |
1307 | #[inline ] |
1308 | fn call0(&self) -> PyResult<Bound<'py, PyAny>> { |
1309 | unsafe { ffi::compat::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) } |
1310 | } |
1311 | |
1312 | fn call1<A>(&self, args: A) -> PyResult<Bound<'py, PyAny>> |
1313 | where |
1314 | A: PyCallArgs<'py>, |
1315 | { |
1316 | args.call_positional(self.as_borrowed(), crate::call::private::Token) |
1317 | } |
1318 | |
1319 | #[inline ] |
1320 | fn call_method<N, A>( |
1321 | &self, |
1322 | name: N, |
1323 | args: A, |
1324 | kwargs: Option<&Bound<'py, PyDict>>, |
1325 | ) -> PyResult<Bound<'py, PyAny>> |
1326 | where |
1327 | N: IntoPyObject<'py, Target = PyString>, |
1328 | A: PyCallArgs<'py>, |
1329 | { |
1330 | if kwargs.is_none() { |
1331 | self.call_method1(name, args) |
1332 | } else { |
1333 | self.getattr(name) |
1334 | .and_then(|method| method.call(args, kwargs)) |
1335 | } |
1336 | } |
1337 | |
1338 | #[inline ] |
1339 | fn call_method0<N>(&self, name: N) -> PyResult<Bound<'py, PyAny>> |
1340 | where |
1341 | N: IntoPyObject<'py, Target = PyString>, |
1342 | { |
1343 | let py = self.py(); |
1344 | let name = name.into_pyobject_or_pyerr(py)?.into_bound(); |
1345 | unsafe { |
1346 | ffi::compat::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()) |
1347 | .assume_owned_or_err(py) |
1348 | } |
1349 | } |
1350 | |
1351 | fn call_method1<N, A>(&self, name: N, args: A) -> PyResult<Bound<'py, PyAny>> |
1352 | where |
1353 | N: IntoPyObject<'py, Target = PyString>, |
1354 | A: PyCallArgs<'py>, |
1355 | { |
1356 | let name = name.into_pyobject_or_pyerr(self.py())?; |
1357 | args.call_method_positional( |
1358 | self.as_borrowed(), |
1359 | name.as_borrowed(), |
1360 | crate::call::private::Token, |
1361 | ) |
1362 | } |
1363 | |
1364 | fn is_truthy(&self) -> PyResult<bool> { |
1365 | let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; |
1366 | err::error_on_minusone(self.py(), v)?; |
1367 | Ok(v != 0) |
1368 | } |
1369 | |
1370 | #[inline ] |
1371 | fn is_none(&self) -> bool { |
1372 | unsafe { ptr::eq(ffi::Py_None(), self.as_ptr()) } |
1373 | } |
1374 | |
1375 | fn is_ellipsis(&self) -> bool { |
1376 | unsafe { ptr::eq(ffi::Py_Ellipsis(), self.as_ptr()) } |
1377 | } |
1378 | |
1379 | fn is_empty(&self) -> PyResult<bool> { |
1380 | self.len().map(|l| l == 0) |
1381 | } |
1382 | |
1383 | fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>> |
1384 | where |
1385 | K: IntoPyObject<'py>, |
1386 | { |
1387 | fn inner<'py>( |
1388 | any: &Bound<'py, PyAny>, |
1389 | key: Borrowed<'_, 'py, PyAny>, |
1390 | ) -> PyResult<Bound<'py, PyAny>> { |
1391 | unsafe { |
1392 | ffi::PyObject_GetItem(any.as_ptr(), key.as_ptr()).assume_owned_or_err(any.py()) |
1393 | } |
1394 | } |
1395 | |
1396 | let py = self.py(); |
1397 | inner( |
1398 | self, |
1399 | key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1400 | ) |
1401 | } |
1402 | |
1403 | fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()> |
1404 | where |
1405 | K: IntoPyObject<'py>, |
1406 | V: IntoPyObject<'py>, |
1407 | { |
1408 | fn inner( |
1409 | any: &Bound<'_, PyAny>, |
1410 | key: Borrowed<'_, '_, PyAny>, |
1411 | value: Borrowed<'_, '_, PyAny>, |
1412 | ) -> PyResult<()> { |
1413 | err::error_on_minusone(any.py(), unsafe { |
1414 | ffi::PyObject_SetItem(any.as_ptr(), key.as_ptr(), value.as_ptr()) |
1415 | }) |
1416 | } |
1417 | |
1418 | let py = self.py(); |
1419 | inner( |
1420 | self, |
1421 | key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1422 | value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1423 | ) |
1424 | } |
1425 | |
1426 | fn del_item<K>(&self, key: K) -> PyResult<()> |
1427 | where |
1428 | K: IntoPyObject<'py>, |
1429 | { |
1430 | fn inner(any: &Bound<'_, PyAny>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> { |
1431 | err::error_on_minusone(any.py(), unsafe { |
1432 | ffi::PyObject_DelItem(any.as_ptr(), key.as_ptr()) |
1433 | }) |
1434 | } |
1435 | |
1436 | let py = self.py(); |
1437 | inner( |
1438 | self, |
1439 | key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1440 | ) |
1441 | } |
1442 | |
1443 | fn try_iter(&self) -> PyResult<Bound<'py, PyIterator>> { |
1444 | PyIterator::from_object(self) |
1445 | } |
1446 | |
1447 | fn iter(&self) -> PyResult<Bound<'py, PyIterator>> { |
1448 | self.try_iter() |
1449 | } |
1450 | |
1451 | fn get_type(&self) -> Bound<'py, PyType> { |
1452 | unsafe { PyType::from_borrowed_type_ptr(self.py(), ffi::Py_TYPE(self.as_ptr())) } |
1453 | } |
1454 | |
1455 | #[inline ] |
1456 | fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { |
1457 | unsafe { ffi::Py_TYPE(self.as_ptr()) } |
1458 | } |
1459 | |
1460 | #[inline ] |
1461 | fn downcast<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> |
1462 | where |
1463 | T: PyTypeCheck, |
1464 | { |
1465 | if T::type_check(self) { |
1466 | // Safety: type_check is responsible for ensuring that the type is correct |
1467 | Ok(unsafe { self.downcast_unchecked() }) |
1468 | } else { |
1469 | Err(DowncastError::new(self, T::NAME)) |
1470 | } |
1471 | } |
1472 | |
1473 | #[inline ] |
1474 | fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>> |
1475 | where |
1476 | T: PyTypeCheck, |
1477 | { |
1478 | if T::type_check(&self) { |
1479 | // Safety: type_check is responsible for ensuring that the type is correct |
1480 | Ok(unsafe { self.downcast_into_unchecked() }) |
1481 | } else { |
1482 | Err(DowncastIntoError::new(self, T::NAME)) |
1483 | } |
1484 | } |
1485 | |
1486 | #[inline ] |
1487 | fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> |
1488 | where |
1489 | T: PyTypeInfo, |
1490 | { |
1491 | if self.is_exact_instance_of::<T>() { |
1492 | // Safety: is_exact_instance_of is responsible for ensuring that the type is correct |
1493 | Ok(unsafe { self.downcast_unchecked() }) |
1494 | } else { |
1495 | Err(DowncastError::new(self, T::NAME)) |
1496 | } |
1497 | } |
1498 | |
1499 | #[inline ] |
1500 | fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>> |
1501 | where |
1502 | T: PyTypeInfo, |
1503 | { |
1504 | if self.is_exact_instance_of::<T>() { |
1505 | // Safety: is_exact_instance_of is responsible for ensuring that the type is correct |
1506 | Ok(unsafe { self.downcast_into_unchecked() }) |
1507 | } else { |
1508 | Err(DowncastIntoError::new(self, T::NAME)) |
1509 | } |
1510 | } |
1511 | |
1512 | #[inline ] |
1513 | unsafe fn downcast_unchecked<T>(&self) -> &Bound<'py, T> { |
1514 | unsafe { &*ptr_from_ref(self).cast() } |
1515 | } |
1516 | |
1517 | #[inline ] |
1518 | unsafe fn downcast_into_unchecked<T>(self) -> Bound<'py, T> { |
1519 | unsafe { std::mem::transmute(self) } |
1520 | } |
1521 | |
1522 | fn extract<'a, T>(&'a self) -> PyResult<T> |
1523 | where |
1524 | T: FromPyObjectBound<'a, 'py>, |
1525 | { |
1526 | FromPyObjectBound::from_py_object_bound(self.as_borrowed()) |
1527 | } |
1528 | |
1529 | fn get_refcnt(&self) -> isize { |
1530 | unsafe { ffi::Py_REFCNT(self.as_ptr()) } |
1531 | } |
1532 | |
1533 | fn repr(&self) -> PyResult<Bound<'py, PyString>> { |
1534 | unsafe { |
1535 | ffi::PyObject_Repr(self.as_ptr()) |
1536 | .assume_owned_or_err(self.py()) |
1537 | .downcast_into_unchecked() |
1538 | } |
1539 | } |
1540 | |
1541 | fn str(&self) -> PyResult<Bound<'py, PyString>> { |
1542 | unsafe { |
1543 | ffi::PyObject_Str(self.as_ptr()) |
1544 | .assume_owned_or_err(self.py()) |
1545 | .downcast_into_unchecked() |
1546 | } |
1547 | } |
1548 | |
1549 | fn hash(&self) -> PyResult<isize> { |
1550 | let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) }; |
1551 | crate::err::error_on_minusone(self.py(), v)?; |
1552 | Ok(v) |
1553 | } |
1554 | |
1555 | fn len(&self) -> PyResult<usize> { |
1556 | let v = unsafe { ffi::PyObject_Size(self.as_ptr()) }; |
1557 | crate::err::error_on_minusone(self.py(), v)?; |
1558 | Ok(v as usize) |
1559 | } |
1560 | |
1561 | fn dir(&self) -> PyResult<Bound<'py, PyList>> { |
1562 | unsafe { |
1563 | ffi::PyObject_Dir(self.as_ptr()) |
1564 | .assume_owned_or_err(self.py()) |
1565 | .downcast_into_unchecked() |
1566 | } |
1567 | } |
1568 | |
1569 | #[inline ] |
1570 | fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult<bool> { |
1571 | let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) }; |
1572 | err::error_on_minusone(self.py(), result)?; |
1573 | Ok(result == 1) |
1574 | } |
1575 | |
1576 | #[inline ] |
1577 | fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool { |
1578 | self.get_type().is(ty) |
1579 | } |
1580 | |
1581 | #[inline ] |
1582 | fn is_instance_of<T: PyTypeInfo>(&self) -> bool { |
1583 | T::is_type_of(self) |
1584 | } |
1585 | |
1586 | #[inline ] |
1587 | fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool { |
1588 | T::is_exact_type_of(self) |
1589 | } |
1590 | |
1591 | fn contains<V>(&self, value: V) -> PyResult<bool> |
1592 | where |
1593 | V: IntoPyObject<'py>, |
1594 | { |
1595 | fn inner(any: &Bound<'_, PyAny>, value: Borrowed<'_, '_, PyAny>) -> PyResult<bool> { |
1596 | match unsafe { ffi::PySequence_Contains(any.as_ptr(), value.as_ptr()) } { |
1597 | 0 => Ok(false), |
1598 | 1 => Ok(true), |
1599 | _ => Err(PyErr::fetch(any.py())), |
1600 | } |
1601 | } |
1602 | |
1603 | let py = self.py(); |
1604 | inner( |
1605 | self, |
1606 | value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), |
1607 | ) |
1608 | } |
1609 | |
1610 | #[cfg (not(any(PyPy, GraalPy)))] |
1611 | fn py_super(&self) -> PyResult<Bound<'py, PySuper>> { |
1612 | PySuper::new(&self.get_type(), self) |
1613 | } |
1614 | } |
1615 | |
1616 | impl<'py> Bound<'py, PyAny> { |
1617 | /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still |
1618 | /// binding the object to the instance. |
1619 | /// |
1620 | /// This is useful when trying to resolve Python's "magic" methods like `__getitem__`, which |
1621 | /// are looked up starting from the type object. This returns an `Option` as it is not |
1622 | /// typically a direct error for the special lookup to fail, as magic methods are optional in |
1623 | /// many situations in which they might be called. |
1624 | /// |
1625 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
1626 | /// to intern `attr_name`. |
1627 | #[allow (dead_code)] // Currently only used with num-complex+abi3, so dead without that. |
1628 | pub(crate) fn lookup_special<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>> |
1629 | where |
1630 | N: IntoPyObject<'py, Target = PyString>, |
1631 | { |
1632 | let py = self.py(); |
1633 | let self_type = self.get_type(); |
1634 | let attr = if let Ok(attr) = self_type.getattr(attr_name) { |
1635 | attr |
1636 | } else { |
1637 | return Ok(None); |
1638 | }; |
1639 | |
1640 | // Manually resolve descriptor protocol. (Faster than going through Python.) |
1641 | if let Some(descr_get) = attr.get_type().get_slot(TP_DESCR_GET) { |
1642 | // attribute is a descriptor, resolve it |
1643 | unsafe { |
1644 | descr_get(attr.as_ptr(), self.as_ptr(), self_type.as_ptr()) |
1645 | .assume_owned_or_err(py) |
1646 | .map(Some) |
1647 | } |
1648 | } else { |
1649 | Ok(Some(attr)) |
1650 | } |
1651 | } |
1652 | } |
1653 | |
1654 | #[cfg (test)] |
1655 | mod tests { |
1656 | use crate::{ |
1657 | basic::CompareOp, |
1658 | ffi, |
1659 | tests::common::generate_unique_module_name, |
1660 | types::{IntoPyDict, PyAny, PyAnyMethods, PyBool, PyInt, PyList, PyModule, PyTypeMethods}, |
1661 | Bound, BoundObject, IntoPyObject, PyTypeInfo, Python, |
1662 | }; |
1663 | use pyo3_ffi::c_str; |
1664 | use std::fmt::Debug; |
1665 | |
1666 | #[test ] |
1667 | fn test_lookup_special() { |
1668 | Python::with_gil(|py| { |
1669 | let module = PyModule::from_code( |
1670 | py, |
1671 | c_str!( |
1672 | r#" |
1673 | class CustomCallable: |
1674 | def __call__(self): |
1675 | return 1 |
1676 | |
1677 | class SimpleInt: |
1678 | def __int__(self): |
1679 | return 1 |
1680 | |
1681 | class InheritedInt(SimpleInt): pass |
1682 | |
1683 | class NoInt: pass |
1684 | |
1685 | class NoDescriptorInt: |
1686 | __int__ = CustomCallable() |
1687 | |
1688 | class InstanceOverrideInt: |
1689 | def __int__(self): |
1690 | return 1 |
1691 | instance_override = InstanceOverrideInt() |
1692 | instance_override.__int__ = lambda self: 2 |
1693 | |
1694 | class ErrorInDescriptorInt: |
1695 | @property |
1696 | def __int__(self): |
1697 | raise ValueError("uh-oh!") |
1698 | |
1699 | class NonHeapNonDescriptorInt: |
1700 | # A static-typed callable that doesn't implement `__get__`. These are pretty hard to come by. |
1701 | __int__ = int |
1702 | "# |
1703 | ), |
1704 | c_str!("test.py" ), |
1705 | &generate_unique_module_name("test" ), |
1706 | ) |
1707 | .unwrap(); |
1708 | |
1709 | let int = crate::intern!(py, "__int__" ); |
1710 | let eval_int = |
1711 | |obj: Bound<'_, PyAny>| obj.lookup_special(int)?.unwrap().call0()?.extract::<u32>(); |
1712 | |
1713 | let simple = module.getattr("SimpleInt" ).unwrap().call0().unwrap(); |
1714 | assert_eq!(eval_int(simple).unwrap(), 1); |
1715 | let inherited = module.getattr("InheritedInt" ).unwrap().call0().unwrap(); |
1716 | assert_eq!(eval_int(inherited).unwrap(), 1); |
1717 | let no_descriptor = module.getattr("NoDescriptorInt" ).unwrap().call0().unwrap(); |
1718 | assert_eq!(eval_int(no_descriptor).unwrap(), 1); |
1719 | let missing = module.getattr("NoInt" ).unwrap().call0().unwrap(); |
1720 | assert!(missing.lookup_special(int).unwrap().is_none()); |
1721 | // Note the instance override should _not_ call the instance method that returns 2, |
1722 | // because that's not how special lookups are meant to work. |
1723 | let instance_override = module.getattr("instance_override" ).unwrap(); |
1724 | assert_eq!(eval_int(instance_override).unwrap(), 1); |
1725 | let descriptor_error = module |
1726 | .getattr("ErrorInDescriptorInt" ) |
1727 | .unwrap() |
1728 | .call0() |
1729 | .unwrap(); |
1730 | assert!(descriptor_error.lookup_special(int).is_err()); |
1731 | let nonheap_nondescriptor = module |
1732 | .getattr("NonHeapNonDescriptorInt" ) |
1733 | .unwrap() |
1734 | .call0() |
1735 | .unwrap(); |
1736 | assert_eq!(eval_int(nonheap_nondescriptor).unwrap(), 0); |
1737 | }) |
1738 | } |
1739 | |
1740 | #[test ] |
1741 | fn test_getattr_opt() { |
1742 | Python::with_gil(|py| { |
1743 | let module = PyModule::from_code( |
1744 | py, |
1745 | c_str!( |
1746 | r#" |
1747 | class Test: |
1748 | class_str_attribute = "class_string" |
1749 | |
1750 | @property |
1751 | def error(self): |
1752 | raise ValueError("This is an intentional error") |
1753 | "# |
1754 | ), |
1755 | c_str!("test.py" ), |
1756 | &generate_unique_module_name("test" ), |
1757 | ) |
1758 | .unwrap(); |
1759 | |
1760 | // Get the class Test |
1761 | let class_test = module.getattr_opt("Test" ).unwrap().unwrap(); |
1762 | |
1763 | // Test attribute that exist |
1764 | let cls_attr_str = class_test |
1765 | .getattr_opt("class_str_attribute" ) |
1766 | .unwrap() |
1767 | .unwrap(); |
1768 | assert_eq!(cls_attr_str.extract::<String>().unwrap(), "class_string" ); |
1769 | |
1770 | // Test non-existent attribute |
1771 | let do_not_exist = class_test.getattr_opt("doNotExist" ).unwrap(); |
1772 | assert!(do_not_exist.is_none()); |
1773 | |
1774 | // Test error attribute |
1775 | let instance = class_test.call0().unwrap(); |
1776 | let error = instance.getattr_opt("error" ); |
1777 | assert!(error.is_err()); |
1778 | assert!(error |
1779 | .unwrap_err() |
1780 | .to_string() |
1781 | .contains("This is an intentional error" )); |
1782 | }); |
1783 | } |
1784 | |
1785 | #[test ] |
1786 | fn test_call_for_non_existing_method() { |
1787 | Python::with_gil(|py| { |
1788 | let a = py.eval(ffi::c_str!("42" ), None, None).unwrap(); |
1789 | a.call_method0("__str__" ).unwrap(); // ok |
1790 | assert!(a.call_method("nonexistent_method" , (1,), None).is_err()); |
1791 | assert!(a.call_method0("nonexistent_method" ).is_err()); |
1792 | assert!(a.call_method1("nonexistent_method" , (1,)).is_err()); |
1793 | }); |
1794 | } |
1795 | |
1796 | #[test ] |
1797 | fn test_call_with_kwargs() { |
1798 | Python::with_gil(|py| { |
1799 | let list = vec![3, 6, 5, 4, 7].into_pyobject(py).unwrap(); |
1800 | let dict = vec![("reverse" , true)].into_py_dict(py).unwrap(); |
1801 | list.call_method("sort" , (), Some(&dict)).unwrap(); |
1802 | assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![7, 6, 5, 4, 3]); |
1803 | }); |
1804 | } |
1805 | |
1806 | #[test ] |
1807 | fn test_call_method0() { |
1808 | Python::with_gil(|py| { |
1809 | let module = PyModule::from_code( |
1810 | py, |
1811 | c_str!( |
1812 | r#" |
1813 | class SimpleClass: |
1814 | def foo(self): |
1815 | return 42 |
1816 | "# |
1817 | ), |
1818 | c_str!(file!()), |
1819 | &generate_unique_module_name("test_module" ), |
1820 | ) |
1821 | .expect("module creation failed" ); |
1822 | |
1823 | let simple_class = module.getattr("SimpleClass" ).unwrap().call0().unwrap(); |
1824 | assert_eq!( |
1825 | simple_class |
1826 | .call_method0("foo" ) |
1827 | .unwrap() |
1828 | .extract::<u32>() |
1829 | .unwrap(), |
1830 | 42 |
1831 | ); |
1832 | }) |
1833 | } |
1834 | |
1835 | #[test ] |
1836 | fn test_type() { |
1837 | Python::with_gil(|py| { |
1838 | let obj = py.eval(ffi::c_str!("42" ), None, None).unwrap(); |
1839 | assert_eq!(obj.get_type().as_type_ptr(), obj.get_type_ptr()); |
1840 | }); |
1841 | } |
1842 | |
1843 | #[test ] |
1844 | fn test_dir() { |
1845 | Python::with_gil(|py| { |
1846 | let obj = py.eval(ffi::c_str!("42" ), None, None).unwrap(); |
1847 | let dir = py |
1848 | .eval(ffi::c_str!("dir(42)" ), None, None) |
1849 | .unwrap() |
1850 | .downcast_into::<PyList>() |
1851 | .unwrap(); |
1852 | let a = obj |
1853 | .dir() |
1854 | .unwrap() |
1855 | .into_iter() |
1856 | .map(|x| x.extract::<String>().unwrap()); |
1857 | let b = dir.into_iter().map(|x| x.extract::<String>().unwrap()); |
1858 | assert!(a.eq(b)); |
1859 | }); |
1860 | } |
1861 | |
1862 | #[test ] |
1863 | fn test_hasattr() { |
1864 | Python::with_gil(|py| { |
1865 | let x = 5i32.into_pyobject(py).unwrap(); |
1866 | assert!(x.is_instance_of::<PyInt>()); |
1867 | |
1868 | assert!(x.hasattr("to_bytes" ).unwrap()); |
1869 | assert!(!x.hasattr("bbbbbbytes" ).unwrap()); |
1870 | }) |
1871 | } |
1872 | |
1873 | #[cfg (feature = "macros" )] |
1874 | #[test ] |
1875 | #[allow (unknown_lints, non_local_definitions)] |
1876 | fn test_hasattr_error() { |
1877 | use crate::exceptions::PyValueError; |
1878 | use crate::prelude::*; |
1879 | |
1880 | #[pyclass(crate = "crate" )] |
1881 | struct GetattrFail; |
1882 | |
1883 | #[pymethods(crate = "crate" )] |
1884 | impl GetattrFail { |
1885 | fn __getattr__(&self, attr: PyObject) -> PyResult<PyObject> { |
1886 | Err(PyValueError::new_err(attr)) |
1887 | } |
1888 | } |
1889 | |
1890 | Python::with_gil(|py| { |
1891 | let obj = Py::new(py, GetattrFail).unwrap(); |
1892 | let obj = obj.bind(py).as_ref(); |
1893 | |
1894 | assert!(obj |
1895 | .hasattr("foo" ) |
1896 | .unwrap_err() |
1897 | .is_instance_of::<PyValueError>(py)); |
1898 | }) |
1899 | } |
1900 | |
1901 | #[test ] |
1902 | fn test_nan_eq() { |
1903 | Python::with_gil(|py| { |
1904 | let nan = py.eval(ffi::c_str!("float('nan')" ), None, None).unwrap(); |
1905 | assert!(nan.compare(&nan).is_err()); |
1906 | }); |
1907 | } |
1908 | |
1909 | #[test ] |
1910 | fn test_any_is_instance_of() { |
1911 | Python::with_gil(|py| { |
1912 | let x = 5i32.into_pyobject(py).unwrap(); |
1913 | assert!(x.is_instance_of::<PyInt>()); |
1914 | |
1915 | let l = vec![&x, &x].into_pyobject(py).unwrap(); |
1916 | assert!(l.is_instance_of::<PyList>()); |
1917 | }); |
1918 | } |
1919 | |
1920 | #[test ] |
1921 | fn test_any_is_instance() { |
1922 | Python::with_gil(|py| { |
1923 | let l = vec![1i8, 2].into_pyobject(py).unwrap(); |
1924 | assert!(l.is_instance(&py.get_type::<PyList>()).unwrap()); |
1925 | }); |
1926 | } |
1927 | |
1928 | #[test ] |
1929 | fn test_any_is_exact_instance_of() { |
1930 | Python::with_gil(|py| { |
1931 | let x = 5i32.into_pyobject(py).unwrap(); |
1932 | assert!(x.is_exact_instance_of::<PyInt>()); |
1933 | |
1934 | let t = PyBool::new(py, true); |
1935 | assert!(t.is_instance_of::<PyInt>()); |
1936 | assert!(!t.is_exact_instance_of::<PyInt>()); |
1937 | assert!(t.is_exact_instance_of::<PyBool>()); |
1938 | |
1939 | let l = vec![&x, &x].into_pyobject(py).unwrap(); |
1940 | assert!(l.is_exact_instance_of::<PyList>()); |
1941 | }); |
1942 | } |
1943 | |
1944 | #[test ] |
1945 | fn test_any_is_exact_instance() { |
1946 | Python::with_gil(|py| { |
1947 | let t = PyBool::new(py, true); |
1948 | assert!(t.is_instance(&py.get_type::<PyInt>()).unwrap()); |
1949 | assert!(!t.is_exact_instance(&py.get_type::<PyInt>())); |
1950 | assert!(t.is_exact_instance(&py.get_type::<PyBool>())); |
1951 | }); |
1952 | } |
1953 | |
1954 | #[test ] |
1955 | fn test_any_contains() { |
1956 | Python::with_gil(|py| { |
1957 | let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8]; |
1958 | let ob = v.into_pyobject(py).unwrap(); |
1959 | |
1960 | let bad_needle = 7i32.into_pyobject(py).unwrap(); |
1961 | assert!(!ob.contains(&bad_needle).unwrap()); |
1962 | |
1963 | let good_needle = 8i32.into_pyobject(py).unwrap(); |
1964 | assert!(ob.contains(&good_needle).unwrap()); |
1965 | |
1966 | let type_coerced_needle = 8f32.into_pyobject(py).unwrap(); |
1967 | assert!(ob.contains(&type_coerced_needle).unwrap()); |
1968 | |
1969 | let n: u32 = 42; |
1970 | let bad_haystack = n.into_pyobject(py).unwrap(); |
1971 | let irrelevant_needle = 0i32.into_pyobject(py).unwrap(); |
1972 | assert!(bad_haystack.contains(&irrelevant_needle).is_err()); |
1973 | }); |
1974 | } |
1975 | |
1976 | // This is intentionally not a test, it's a generic function used by the tests below. |
1977 | fn test_eq_methods_generic<'a, T>(list: &'a [T]) |
1978 | where |
1979 | T: PartialEq + PartialOrd, |
1980 | for<'py> &'a T: IntoPyObject<'py>, |
1981 | for<'py> <&'a T as IntoPyObject<'py>>::Error: Debug, |
1982 | { |
1983 | Python::with_gil(|py| { |
1984 | for a in list { |
1985 | for b in list { |
1986 | let a_py = a.into_pyobject(py).unwrap().into_any().into_bound(); |
1987 | let b_py = b.into_pyobject(py).unwrap().into_any().into_bound(); |
1988 | |
1989 | assert_eq!( |
1990 | a.lt(b), |
1991 | a_py.lt(&b_py).unwrap(), |
1992 | "{} < {} should be {}." , |
1993 | a_py, |
1994 | b_py, |
1995 | a.lt(b) |
1996 | ); |
1997 | assert_eq!( |
1998 | a.le(b), |
1999 | a_py.le(&b_py).unwrap(), |
2000 | "{} <= {} should be {}." , |
2001 | a_py, |
2002 | b_py, |
2003 | a.le(b) |
2004 | ); |
2005 | assert_eq!( |
2006 | a.eq(b), |
2007 | a_py.eq(&b_py).unwrap(), |
2008 | "{} == {} should be {}." , |
2009 | a_py, |
2010 | b_py, |
2011 | a.eq(b) |
2012 | ); |
2013 | assert_eq!( |
2014 | a.ne(b), |
2015 | a_py.ne(&b_py).unwrap(), |
2016 | "{} != {} should be {}." , |
2017 | a_py, |
2018 | b_py, |
2019 | a.ne(b) |
2020 | ); |
2021 | assert_eq!( |
2022 | a.gt(b), |
2023 | a_py.gt(&b_py).unwrap(), |
2024 | "{} > {} should be {}." , |
2025 | a_py, |
2026 | b_py, |
2027 | a.gt(b) |
2028 | ); |
2029 | assert_eq!( |
2030 | a.ge(b), |
2031 | a_py.ge(&b_py).unwrap(), |
2032 | "{} >= {} should be {}." , |
2033 | a_py, |
2034 | b_py, |
2035 | a.ge(b) |
2036 | ); |
2037 | } |
2038 | } |
2039 | }); |
2040 | } |
2041 | |
2042 | #[test ] |
2043 | fn test_eq_methods_integers() { |
2044 | let ints = [-4, -4, 1, 2, 0, -100, 1_000_000]; |
2045 | test_eq_methods_generic::<i32>(&ints); |
2046 | } |
2047 | |
2048 | #[test ] |
2049 | fn test_eq_methods_strings() { |
2050 | let strings = ["Let's" , "test" , "some" , "eq" , "methods" ]; |
2051 | test_eq_methods_generic::<&str>(&strings); |
2052 | } |
2053 | |
2054 | #[test ] |
2055 | fn test_eq_methods_floats() { |
2056 | let floats = [ |
2057 | -1.0, |
2058 | 2.5, |
2059 | 0.0, |
2060 | 3.0, |
2061 | std::f64::consts::PI, |
2062 | 10.0, |
2063 | 10.0 / 3.0, |
2064 | -1_000_000.0, |
2065 | ]; |
2066 | test_eq_methods_generic::<f64>(&floats); |
2067 | } |
2068 | |
2069 | #[test ] |
2070 | fn test_eq_methods_bools() { |
2071 | let bools = [true, false]; |
2072 | test_eq_methods_generic::<bool>(&bools); |
2073 | } |
2074 | |
2075 | #[test ] |
2076 | fn test_rich_compare_type_error() { |
2077 | Python::with_gil(|py| { |
2078 | let py_int = 1i32.into_pyobject(py).unwrap(); |
2079 | let py_str = "1" .into_pyobject(py).unwrap(); |
2080 | |
2081 | assert!(py_int.rich_compare(&py_str, CompareOp::Lt).is_err()); |
2082 | assert!(!py_int |
2083 | .rich_compare(py_str, CompareOp::Eq) |
2084 | .unwrap() |
2085 | .is_truthy() |
2086 | .unwrap()); |
2087 | }) |
2088 | } |
2089 | |
2090 | #[test ] |
2091 | #[allow (deprecated)] |
2092 | fn test_is_ellipsis() { |
2093 | Python::with_gil(|py| { |
2094 | let v = py |
2095 | .eval(ffi::c_str!("..." ), None, None) |
2096 | .map_err(|e| e.display(py)) |
2097 | .unwrap(); |
2098 | |
2099 | assert!(v.is_ellipsis()); |
2100 | |
2101 | let not_ellipsis = 5i32.into_pyobject(py).unwrap(); |
2102 | assert!(!not_ellipsis.is_ellipsis()); |
2103 | }); |
2104 | } |
2105 | |
2106 | #[test ] |
2107 | fn test_is_callable() { |
2108 | Python::with_gil(|py| { |
2109 | assert!(PyList::type_object(py).is_callable()); |
2110 | |
2111 | let not_callable = 5i32.into_pyobject(py).unwrap(); |
2112 | assert!(!not_callable.is_callable()); |
2113 | }); |
2114 | } |
2115 | |
2116 | #[test ] |
2117 | fn test_is_empty() { |
2118 | Python::with_gil(|py| { |
2119 | let empty_list = PyList::empty(py).into_any(); |
2120 | assert!(empty_list.is_empty().unwrap()); |
2121 | |
2122 | let list = PyList::new(py, vec![1, 2, 3]).unwrap().into_any(); |
2123 | assert!(!list.is_empty().unwrap()); |
2124 | |
2125 | let not_container = 5i32.into_pyobject(py).unwrap(); |
2126 | assert!(not_container.is_empty().is_err()); |
2127 | }); |
2128 | } |
2129 | |
2130 | #[cfg (feature = "macros" )] |
2131 | #[test ] |
2132 | #[allow (unknown_lints, non_local_definitions)] |
2133 | fn test_fallible_dir() { |
2134 | use crate::exceptions::PyValueError; |
2135 | use crate::prelude::*; |
2136 | |
2137 | #[pyclass(crate = "crate" )] |
2138 | struct DirFail; |
2139 | |
2140 | #[pymethods(crate = "crate" )] |
2141 | impl DirFail { |
2142 | fn __dir__(&self) -> PyResult<PyObject> { |
2143 | Err(PyValueError::new_err("uh-oh!" )) |
2144 | } |
2145 | } |
2146 | |
2147 | Python::with_gil(|py| { |
2148 | let obj = Bound::new(py, DirFail).unwrap(); |
2149 | assert!(obj.dir().unwrap_err().is_instance_of::<PyValueError>(py)); |
2150 | }) |
2151 | } |
2152 | } |
2153 | |