From 964304e8bdbd81c813a441f64634749039682008 Mon Sep 17 00:00:00 2001 From: Moreal Date: Sat, 11 Dec 2021 23:54:48 +0900 Subject: [PATCH] Expose `types.GenericAlias.__getitem__` --- vm/src/builtins/genericalias.rs | 103 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/vm/src/builtins/genericalias.rs b/vm/src/builtins/genericalias.rs index 6f3956eb2d..c272e59daa 100644 --- a/vm/src/builtins/genericalias.rs +++ b/vm/src/builtins/genericalias.rs @@ -126,6 +126,58 @@ impl PyGenericAlias { self.origin.as_object().to_owned() } + #[pymethod(magic)] + fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { + let num_params = self.parameters.len(); + if num_params == 0 { + return Err(vm.new_type_error(format!( + "There are no type variables left in {}", + self.repr(vm)? + ))); + } + + let items = PyTupleRef::try_from_object(vm, needle.clone()); + let arg_items = match items { + Ok(ref tuple) => tuple.as_slice(), + Err(_) => std::slice::from_ref(&needle), + }; + + let num_items = arg_items.len(); + if num_params != num_items { + let plural = if num_items > num_params { + "many" + } else { + "few" + }; + return Err(vm.new_type_error(format!( + "Too {} arguments for {}", + plural, + self.repr(vm)? + ))); + } + + let new_args = self + .args + .as_slice() + .iter() + .map(|arg| { + if is_typevar(arg) { + let idx = tuple_index(&self.parameters, arg).unwrap(); + Ok(arg_items[idx].clone()) + } else { + subs_tvars(arg.clone(), &self.parameters, arg_items, vm) + } + }) + .collect::>>()?; + + Ok(PyGenericAlias::new( + self.origin.clone(), + PyTuple::new_ref(new_args, &vm.ctx).into(), + vm, + ) + .into_object(vm)) + } + #[pymethod(magic)] fn dir(&self, vm: &VirtualMachine) -> PyResult { let dir = vm.dir(Some(self.origin()))?; @@ -238,57 +290,6 @@ fn subs_tvars( } impl PyGenericAlias { - fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { - let num_params = self.parameters.len(); - if num_params == 0 { - return Err(vm.new_type_error(format!( - "There are no type variables left in {}", - self.repr(vm)? - ))); - } - - let items = PyTupleRef::try_from_object(vm, needle.clone()); - let arg_items = match items { - Ok(ref tuple) => tuple.as_slice(), - Err(_) => std::slice::from_ref(&needle), - }; - - let num_items = arg_items.len(); - if num_params != num_items { - let plural = if num_items > num_params { - "many" - } else { - "few" - }; - return Err(vm.new_type_error(format!( - "Too {} arguments for {}", - plural, - self.repr(vm)? - ))); - } - - let new_args = self - .args - .as_slice() - .iter() - .map(|arg| { - if is_typevar(arg) { - let idx = tuple_index(&self.parameters, arg).unwrap(); - Ok(arg_items[idx].clone()) - } else { - subs_tvars(arg.clone(), &self.parameters, arg_items, vm) - } - }) - .collect::>>()?; - - Ok(PyGenericAlias::new( - self.origin.clone(), - PyTuple::new_ref(new_args, &vm.ctx).into(), - vm, - ) - .into_object(vm)) - } - const MAPPING_METHODS: PyMappingMethods = PyMappingMethods { length: None, subscript: Some(|mapping, needle, vm| {