CPython _PyObject_GenericGetAttrWithDict
(
&self,
name_str: &Py<PyStr>,
dict: Option<PyDictRef>,
vm: &VirtualMachine,
)
| 224 | |
| 225 | /// CPython _PyObject_GenericGetAttrWithDict |
| 226 | pub fn generic_getattr_opt( |
| 227 | &self, |
| 228 | name_str: &Py<PyStr>, |
| 229 | dict: Option<PyDictRef>, |
| 230 | vm: &VirtualMachine, |
| 231 | ) -> PyResult<Option<PyObjectRef>> { |
| 232 | let name = name_str.as_wtf8(); |
| 233 | let obj_cls = self.class(); |
| 234 | let cls_attr_name = vm.ctx.interned_str(name_str); |
| 235 | let cls_attr = match cls_attr_name.and_then(|name| obj_cls.get_attr(name)) { |
| 236 | Some(descr) => { |
| 237 | let descr_cls = descr.class(); |
| 238 | let descr_get = descr_cls.slots.descr_get.load(); |
| 239 | if let Some(descr_get) = descr_get |
| 240 | && descr_cls.slots.descr_set.load().is_some() |
| 241 | { |
| 242 | let cls = obj_cls.to_owned().into(); |
| 243 | return descr_get(descr, Some(self.to_owned()), Some(cls), vm).map(Some); |
| 244 | } |
| 245 | Some((descr, descr_get)) |
| 246 | } |
| 247 | None => None, |
| 248 | }; |
| 249 | |
| 250 | let dict = dict.or_else(|| self.dict()); |
| 251 | |
| 252 | let attr = if let Some(dict) = dict { |
| 253 | dict.get_item_opt(name, vm)? |
| 254 | } else { |
| 255 | None |
| 256 | }; |
| 257 | |
| 258 | if let Some(obj_attr) = attr { |
| 259 | Ok(Some(obj_attr)) |
| 260 | } else if let Some((attr, descr_get)) = cls_attr { |
| 261 | match descr_get { |
| 262 | Some(descr_get) => { |
| 263 | let cls = obj_cls.to_owned().into(); |
| 264 | descr_get(attr, Some(self.to_owned()), Some(cls), vm).map(Some) |
| 265 | } |
| 266 | None => Ok(Some(attr)), |
| 267 | } |
| 268 | } else { |
| 269 | Ok(None) |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | pub fn del_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult<()> { |
| 274 | let attr_name = attr_name.as_pystr(&vm.ctx); |
no test coverage detected