(obj: PyObjectRef, name: &Py<PyStr>, vm: &VirtualMachine)
| 20 | |
| 21 | impl PyMethod { |
| 22 | pub fn get(obj: PyObjectRef, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult<Self> { |
| 23 | let cls = obj.class(); |
| 24 | let getattro = cls.slots.getattro.load().unwrap(); |
| 25 | if getattro as usize != PyBaseObject::getattro as *const () as usize { |
| 26 | return obj.get_attr(name, vm).map(Self::Attribute); |
| 27 | } |
| 28 | |
| 29 | // any correct method name is always interned already. |
| 30 | let interned_name = vm.ctx.interned_str(name); |
| 31 | let mut is_method = false; |
| 32 | |
| 33 | let cls_attr = match interned_name.and_then(|name| cls.get_attr(name)) { |
| 34 | Some(descr) => { |
| 35 | let descr_cls = descr.class(); |
| 36 | let descr_get = if descr_cls |
| 37 | .slots |
| 38 | .flags |
| 39 | .has_feature(PyTypeFlags::METHOD_DESCRIPTOR) |
| 40 | { |
| 41 | // For classmethods, we need descr_get to convert instance to class |
| 42 | if let Some(method_descr) = descr.downcast_ref::<PyMethodDescriptor>() |
| 43 | && method_descr.method.flags.contains(PyMethodFlags::CLASS) |
| 44 | { |
| 45 | descr_cls.slots.descr_get.load() |
| 46 | } else { |
| 47 | is_method = true; |
| 48 | None |
| 49 | } |
| 50 | } else { |
| 51 | let descr_get = descr_cls.slots.descr_get.load(); |
| 52 | if let Some(descr_get) = descr_get |
| 53 | && descr_cls.slots.descr_set.load().is_some() |
| 54 | { |
| 55 | let cls = cls.to_owned().into(); |
| 56 | return descr_get(descr, Some(obj), Some(cls), vm).map(Self::Attribute); |
| 57 | } |
| 58 | descr_get |
| 59 | }; |
| 60 | Some((descr, descr_get)) |
| 61 | } |
| 62 | None => None, |
| 63 | }; |
| 64 | |
| 65 | if let Some(dict) = obj.dict() |
| 66 | && let Some(attr) = dict.get_item_opt(name, vm)? |
| 67 | { |
| 68 | return Ok(Self::Attribute(attr)); |
| 69 | } |
| 70 | |
| 71 | if let Some((attr, descr_get)) = cls_attr { |
| 72 | match descr_get { |
| 73 | None if is_method => Ok(Self::Function { |
| 74 | target: obj, |
| 75 | func: attr, |
| 76 | }), |
| 77 | Some(descr_get) => { |
| 78 | let cls = cls.to_owned().into(); |
| 79 | descr_get(attr, Some(obj), Some(cls), vm).map(Self::Attribute) |
no test coverage detected