(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine)
| 236 | type Args = crate::function::PosArgs; |
| 237 | |
| 238 | fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { |
| 239 | let args: Self::Args = args.bind(vm)?; |
| 240 | let args = args.into_vec(); |
| 241 | // Validate exactly 2 positional arguments |
| 242 | if args.len() != 2 { |
| 243 | return Err(vm.new_type_error(format!( |
| 244 | "BaseExceptionGroup.__new__() takes exactly 2 positional arguments ({} given)", |
| 245 | args.len() |
| 246 | ))); |
| 247 | } |
| 248 | |
| 249 | // Validate message is str |
| 250 | let message = args[0].clone(); |
| 251 | if !message.fast_isinstance(vm.ctx.types.str_type) { |
| 252 | return Err(vm.new_type_error(format!( |
| 253 | "argument 1 must be str, not {}", |
| 254 | message.class().name() |
| 255 | ))); |
| 256 | } |
| 257 | |
| 258 | // Validate exceptions is a sequence (not set or None) |
| 259 | let exceptions_arg = &args[1]; |
| 260 | |
| 261 | // Check for set/frozenset (not a sequence - unordered) |
| 262 | if exceptions_arg.fast_isinstance(vm.ctx.types.set_type) |
| 263 | || exceptions_arg.fast_isinstance(vm.ctx.types.frozenset_type) |
| 264 | { |
| 265 | return Err(vm.new_type_error("second argument (exceptions) must be a sequence")); |
| 266 | } |
| 267 | |
| 268 | // Check for None |
| 269 | if exceptions_arg.is(&vm.ctx.none) { |
| 270 | return Err(vm.new_type_error("second argument (exceptions) must be a sequence")); |
| 271 | } |
| 272 | |
| 273 | let exceptions: Vec<PyObjectRef> = exceptions_arg.try_to_value(vm).map_err(|_| { |
| 274 | vm.new_type_error("second argument (exceptions) must be a sequence") |
| 275 | })?; |
| 276 | |
| 277 | // Validate non-empty |
| 278 | if exceptions.is_empty() { |
| 279 | return Err( |
| 280 | vm.new_value_error("second argument (exceptions) must be a non-empty sequence") |
| 281 | ); |
| 282 | } |
| 283 | |
| 284 | // Validate all items are BaseException instances |
| 285 | let mut has_non_exception = false; |
| 286 | for (i, exc) in exceptions.iter().enumerate() { |
| 287 | if !exc.fast_isinstance(vm.ctx.exceptions.base_exception_type) { |
| 288 | return Err(vm.new_value_error(format!( |
| 289 | "Item {} of second argument (exceptions) is not an exception", |
| 290 | i |
| 291 | ))); |
| 292 | } |
| 293 | // Check if any exception is not an Exception subclass |
| 294 | // With dynamic ExceptionGroup (inherits from both BaseExceptionGroup and Exception), |
| 295 | // ExceptionGroup instances are automatically instances of Exception |
nothing calls this directly
no test coverage detected