1pub use typevar::*;
4
5#[pymodule(sub)]
6pub(crate) mod typevar {
7 use crate::{
8 AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
9 builtins::{PyTuple, PyTupleRef, PyType, PyTypeRef, make_union},
10 common::lock::PyMutex,
11 function::{FuncArgs, PyComparisonValue},
12 protocol::PyNumberMethods,
13 stdlib::_typing::{call_typing_func_object, decl::const_evaluator_alloc},
14 types::{AsNumber, Comparable, Constructor, Iterable, PyComparisonOp, Representable},
15 };
16
17 fn type_check(arg: PyObjectRef, msg: &str, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
18 if vm.is_none(&arg) {
20 return Ok(arg.class().to_owned().into());
21 }
22 let message_str: PyObjectRef = vm.ctx.new_str(msg).into();
23 call_typing_func_object(vm, "_type_check", (arg, message_str))
24 }
25
26 fn variance_repr(
27 name: &str,
28 infer_variance: bool,
29 covariant: bool,
30 contravariant: bool,
31 ) -> String {
32 if infer_variance {
33 return name.to_owned();
34 }
35 let prefix = if covariant {
36 '+'
37 } else if contravariant {
38 '-'
39 } else {
40 '~'
41 };
42 format!("{prefix}{name}")
43 }
44
45 fn caller(vm: &VirtualMachine) -> Option<PyObjectRef> {
53 let frame = vm.current_frame()?;
54
55 frame.globals.get_item("__name__", vm).ok()
58 }
59
60 fn set_module_from_caller(obj: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
63 let module_value: PyObjectRef = if let Some(module_name) = caller(vm) {
66 if let Ok(name_str) = module_name.str(vm)
68 && let Some(name) = name_str.to_str()
69 && (name == "builtins" || name.starts_with('<'))
70 {
71 return Ok(());
72 }
73 module_name
74 } else {
75 vm.ctx.none()
76 };
77 obj.set_attr("__module__", module_value, vm)?;
78 Ok(())
79 }
80
81 #[pyattr]
82 #[pyclass(name = "TypeVar", module = "typing")]
83 #[derive(Debug, PyPayload)]
84 #[allow(dead_code)]
85 pub struct TypeVar {
86 name: PyObjectRef, bound: PyMutex<PyObjectRef>,
88 evaluate_bound: PyObjectRef,
89 constraints: PyMutex<PyObjectRef>,
90 evaluate_constraints: PyObjectRef,
91 default_value: PyMutex<PyObjectRef>,
92 evaluate_default: PyMutex<PyObjectRef>,
93 covariant: bool,
94 contravariant: bool,
95 infer_variance: bool,
96 }
97 #[pyclass(
98 flags(HAS_DICT, HAS_WEAKREF),
99 with(AsNumber, Constructor, Representable)
100 )]
101 impl TypeVar {
102 #[pymethod]
103 fn __mro_entries__(&self, _bases: PyObjectRef, vm: &VirtualMachine) -> PyResult {
104 Err(vm.new_type_error("Cannot subclass an instance of TypeVar"))
105 }
106
107 #[pygetset]
108 fn __name__(&self) -> PyObjectRef {
109 self.name.clone()
110 }
111
112 #[pygetset]
113 fn __constraints__(&self, vm: &VirtualMachine) -> PyResult {
114 let mut constraints = self.constraints.lock();
115 if !vm.is_none(&constraints) {
116 return Ok(constraints.clone());
117 }
118 let r = if !vm.is_none(&self.evaluate_constraints) {
119 *constraints = self.evaluate_constraints.call((1i32,), vm)?;
120 constraints.clone()
121 } else {
122 vm.ctx.empty_tuple.clone().into()
123 };
124 Ok(r)
125 }
126
127 #[pygetset]
128 fn __bound__(&self, vm: &VirtualMachine) -> PyResult {
129 let mut bound = self.bound.lock();
130 if !vm.is_none(&bound) {
131 return Ok(bound.clone());
132 }
133 let r = if !vm.is_none(&self.evaluate_bound) {
134 *bound = self.evaluate_bound.call((1i32,), vm)?;
135 bound.clone()
136 } else {
137 vm.ctx.none()
138 };
139 Ok(r)
140 }
141
142 #[pygetset]
143 const fn __covariant__(&self) -> bool {
144 self.covariant
145 }
146
147 #[pygetset]
148 const fn __contravariant__(&self) -> bool {
149 self.contravariant
150 }
151
152 #[pygetset]
153 const fn __infer_variance__(&self) -> bool {
154 self.infer_variance
155 }
156
157 #[pygetset]
158 fn __default__(&self, vm: &VirtualMachine) -> PyResult {
159 {
160 let default_value = self.default_value.lock();
161 if !default_value.is(&vm.ctx.typing_no_default) {
162 return Ok(default_value.clone());
163 }
164 }
165 let evaluator = self.evaluate_default.lock().clone();
166 if !vm.is_none(&evaluator) {
167 let result = evaluator.call((1i32,), vm)?;
168 *self.default_value.lock() = result.clone();
169 Ok(result)
170 } else {
171 Ok(vm.ctx.typing_no_default.clone().into())
172 }
173 }
174
175 #[pygetset]
176 fn evaluate_bound(&self, vm: &VirtualMachine) -> PyResult {
177 if !vm.is_none(&self.evaluate_bound) {
178 return Ok(self.evaluate_bound.clone());
179 }
180 let bound = self.bound.lock();
181 if !vm.is_none(&bound) {
182 return Ok(const_evaluator_alloc(bound.clone(), vm));
183 }
184 Ok(vm.ctx.none())
185 }
186
187 #[pygetset]
188 fn evaluate_constraints(&self, vm: &VirtualMachine) -> PyResult {
189 if !vm.is_none(&self.evaluate_constraints) {
190 return Ok(self.evaluate_constraints.clone());
191 }
192 let constraints = self.constraints.lock();
193 if !vm.is_none(&constraints) {
194 return Ok(const_evaluator_alloc(constraints.clone(), vm));
195 }
196 Ok(vm.ctx.none())
197 }
198
199 #[pygetset]
200 fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
201 let evaluator = self.evaluate_default.lock().clone();
202 if !vm.is_none(&evaluator) {
203 return Ok(evaluator);
204 }
205 let default_value = self.default_value.lock().clone();
206 if !default_value.is(&vm.ctx.typing_no_default) {
207 return Ok(const_evaluator_alloc(default_value, vm));
208 }
209 Ok(vm.ctx.none())
210 }
211
212 #[pymethod]
213 fn __typing_subst__(
214 zelf: crate::PyRef<Self>,
215 arg: PyObjectRef,
216 vm: &VirtualMachine,
217 ) -> PyResult {
218 let self_obj: PyObjectRef = zelf.into();
219 call_typing_func_object(vm, "_typevar_subst", (self_obj, arg))
220 }
221
222 #[pymethod]
223 fn __reduce__(&self) -> PyObjectRef {
224 self.name.clone()
225 }
226
227 #[pymethod]
228 fn has_default(&self, vm: &VirtualMachine) -> bool {
229 if !vm.is_none(&self.evaluate_default.lock()) {
230 return true;
231 }
232 let default_value = self.default_value.lock();
233 !default_value.is(&vm.ctx.typing_no_default)
235 }
236
237 #[pymethod]
238 fn __typing_prepare_subst__(
239 zelf: crate::PyRef<Self>,
240 alias: PyObjectRef,
241 args: PyObjectRef,
242 vm: &VirtualMachine,
243 ) -> PyResult {
244 let args_tuple =
246 if let Ok(tuple) = args.try_to_ref::<rustpython_vm::builtins::PyTuple>(vm) {
247 tuple
248 } else {
249 return Ok(args);
250 };
251
252 let parameters = alias.get_attr(identifier!(vm, __parameters__), vm)?;
254 let params_tuple: PyTupleRef = parameters.try_into_value(vm)?;
255
256 let self_obj: PyObjectRef = zelf.to_owned().into();
258 let param_index = params_tuple.iter().position(|p| p.is(&self_obj));
259
260 if let Some(index) = param_index {
261 if args_tuple.len() <= index && zelf.has_default(vm) {
263 let mut new_args: Vec<PyObjectRef> = args_tuple.iter().cloned().collect();
265
266 while new_args.len() <= index {
268 if new_args.len() == index {
270 let default_val = zelf.__default__(vm)?;
271 new_args.push(default_val);
272 } else {
273 break;
275 }
276 }
277
278 return Ok(rustpython_vm::builtins::PyTuple::new_ref(new_args, &vm.ctx).into());
279 }
280 }
281
282 Ok(args)
284 }
285 }
286
287 impl Representable for TypeVar {
288 #[inline(always)]
289 fn repr_str(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
290 let name = zelf.name.str_utf8(vm)?;
291 Ok(variance_repr(
292 name.as_str(),
293 zelf.infer_variance,
294 zelf.covariant,
295 zelf.contravariant,
296 ))
297 }
298 }
299
300 impl AsNumber for TypeVar {
301 fn as_number() -> &'static PyNumberMethods {
302 static AS_NUMBER: PyNumberMethods = PyNumberMethods {
303 or: Some(|a, b, vm| {
304 let args = PyTuple::new_ref(vec![a.to_owned(), b.to_owned()], &vm.ctx);
305 make_union(&args, vm)
306 }),
307 ..PyNumberMethods::NOT_IMPLEMENTED
308 };
309 &AS_NUMBER
310 }
311 }
312
313 impl Constructor for TypeVar {
314 type Args = FuncArgs;
315
316 fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
317 let typevar = <Self as Constructor>::py_new(&cls, args, vm)?;
318 let obj = typevar.into_ref_with_type(vm, cls)?;
319 let obj_ref: PyObjectRef = obj.into();
320 set_module_from_caller(&obj_ref, vm)?;
321 Ok(obj_ref)
322 }
323
324 fn py_new(_cls: &Py<PyType>, args: Self::Args, vm: &VirtualMachine) -> PyResult<Self> {
325 let mut kwargs = args.kwargs;
326 let (name, constraints) = if args.args.is_empty() {
328 if let Some(name) = kwargs.swap_remove("name") {
330 (name, vec![])
331 } else {
332 return Err(
333 vm.new_type_error("TypeVar() missing required argument: 'name' (pos 1)")
334 );
335 }
336 } else if args.args.len() == 1 {
337 (args.args[0].clone(), vec![])
338 } else {
339 let name = args.args[0].clone();
340 let constraints = args.args[1..].to_vec();
341 (name, constraints)
342 };
343
344 let bound = kwargs.swap_remove("bound");
345 let covariant = kwargs
346 .swap_remove("covariant")
347 .map(|v| v.try_to_bool(vm))
348 .transpose()?
349 .unwrap_or(false);
350 let contravariant = kwargs
351 .swap_remove("contravariant")
352 .map(|v| v.try_to_bool(vm))
353 .transpose()?
354 .unwrap_or(false);
355 let infer_variance = kwargs
356 .swap_remove("infer_variance")
357 .map(|v| v.try_to_bool(vm))
358 .transpose()?
359 .unwrap_or(false);
360 let default = kwargs.swap_remove("default");
361
362 if !kwargs.is_empty() {
364 let unexpected_keys: Vec<String> = kwargs.keys().map(|s| s.to_string()).collect();
365 return Err(vm.new_type_error(format!(
366 "TypeVar() got unexpected keyword argument(s): {}",
367 unexpected_keys.join(", ")
368 )));
369 }
370
371 if covariant && contravariant {
373 return Err(vm.new_value_error("Bivariant type variables are not supported."));
374 }
375
376 if infer_variance && (covariant || contravariant) {
377 return Err(vm.new_value_error("Variance cannot be specified with infer_variance"));
378 }
379
380 let (constraints_obj, evaluate_constraints) = if !constraints.is_empty() {
382 if constraints.len() == 1 {
384 return Err(vm.new_type_error("A single constraint is not allowed"));
385 }
386 if bound.is_some() {
387 return Err(vm.new_type_error("Constraints cannot be used with bound"));
388 }
389 let constraints_tuple = vm.ctx.new_tuple(constraints);
390 (constraints_tuple.into(), vm.ctx.none())
391 } else {
392 (vm.ctx.none(), vm.ctx.none())
393 };
394
395 let (bound_obj, evaluate_bound) = if let Some(bound) = bound {
397 if vm.is_none(&bound) {
398 (vm.ctx.none(), vm.ctx.none())
399 } else {
400 let bound = type_check(bound, "Bound must be a type.", vm)?;
402 (bound, vm.ctx.none())
403 }
404 } else {
405 (vm.ctx.none(), vm.ctx.none())
406 };
407
408 let (default_value, evaluate_default) = if let Some(default) = default {
410 (default, vm.ctx.none())
411 } else {
412 (vm.ctx.typing_no_default.clone().into(), vm.ctx.none())
414 };
415
416 Ok(Self {
417 name,
418 bound: PyMutex::new(bound_obj),
419 evaluate_bound,
420 constraints: PyMutex::new(constraints_obj),
421 evaluate_constraints,
422 default_value: PyMutex::new(default_value),
423 evaluate_default: PyMutex::new(evaluate_default),
424 covariant,
425 contravariant,
426 infer_variance,
427 })
428 }
429 }
430
431 impl TypeVar {
432 pub fn new(
433 vm: &VirtualMachine,
434 name: PyObjectRef,
435 evaluate_bound: PyObjectRef,
436 evaluate_constraints: PyObjectRef,
437 ) -> Self {
438 Self {
439 name,
440 bound: PyMutex::new(vm.ctx.none()),
441 evaluate_bound,
442 constraints: PyMutex::new(vm.ctx.none()),
443 evaluate_constraints,
444 default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
445 evaluate_default: PyMutex::new(vm.ctx.none()),
446 covariant: false,
447 contravariant: false,
448 infer_variance: true,
449 }
450 }
451 }
452
453 #[pyattr]
454 #[pyclass(name = "ParamSpec", module = "typing")]
455 #[derive(Debug, PyPayload)]
456 #[allow(dead_code)]
457 pub struct ParamSpec {
458 name: PyObjectRef,
459 bound: Option<PyObjectRef>,
460 default_value: PyMutex<PyObjectRef>,
461 evaluate_default: PyMutex<PyObjectRef>,
462 covariant: bool,
463 contravariant: bool,
464 infer_variance: bool,
465 }
466
467 #[pyclass(
468 flags(HAS_DICT, HAS_WEAKREF),
469 with(AsNumber, Constructor, Representable)
470 )]
471 impl ParamSpec {
472 #[pymethod]
473 fn __mro_entries__(&self, _bases: PyObjectRef, vm: &VirtualMachine) -> PyResult {
474 Err(vm.new_type_error("Cannot subclass an instance of ParamSpec"))
475 }
476
477 #[pygetset]
478 fn __name__(&self) -> PyObjectRef {
479 self.name.clone()
480 }
481
482 #[pygetset]
483 fn args(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyResult {
484 let self_obj: PyObjectRef = zelf.into();
485 let psa = ParamSpecArgs {
486 __origin__: self_obj,
487 };
488 Ok(psa.into_ref(&vm.ctx).into())
489 }
490
491 #[pygetset]
492 fn kwargs(zelf: crate::PyRef<Self>, vm: &VirtualMachine) -> PyResult {
493 let self_obj: PyObjectRef = zelf.into();
494 let psk = ParamSpecKwargs {
495 __origin__: self_obj,
496 };
497 Ok(psk.into_ref(&vm.ctx).into())
498 }
499
500 #[pygetset]
501 fn __bound__(&self, vm: &VirtualMachine) -> PyObjectRef {
502 if let Some(bound) = self.bound.clone() {
503 return bound;
504 }
505 vm.ctx.none()
506 }
507
508 #[pygetset]
509 const fn __covariant__(&self) -> bool {
510 self.covariant
511 }
512
513 #[pygetset]
514 const fn __contravariant__(&self) -> bool {
515 self.contravariant
516 }
517
518 #[pygetset]
519 const fn __infer_variance__(&self) -> bool {
520 self.infer_variance
521 }
522
523 #[pygetset]
524 fn __default__(&self, vm: &VirtualMachine) -> PyResult {
525 {
526 let default_value = self.default_value.lock();
527 if !default_value.is(&vm.ctx.typing_no_default) {
528 return Ok(default_value.clone());
529 }
530 }
531 let evaluator = self.evaluate_default.lock().clone();
532 if !vm.is_none(&evaluator) {
533 let result = evaluator.call((1i32,), vm)?;
534 *self.default_value.lock() = result.clone();
535 Ok(result)
536 } else {
537 Ok(vm.ctx.typing_no_default.clone().into())
538 }
539 }
540
541 #[pygetset]
542 fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
543 let evaluator = self.evaluate_default.lock().clone();
544 if !vm.is_none(&evaluator) {
545 return Ok(evaluator);
546 }
547 let default_value = self.default_value.lock().clone();
548 if !default_value.is(&vm.ctx.typing_no_default) {
549 return Ok(const_evaluator_alloc(default_value, vm));
550 }
551 Ok(vm.ctx.none())
552 }
553
554 #[pymethod]
555 fn __reduce__(&self) -> PyResult {
556 Ok(self.name.clone())
557 }
558
559 #[pymethod]
560 fn has_default(&self, vm: &VirtualMachine) -> bool {
561 if !vm.is_none(&self.evaluate_default.lock()) {
562 return true;
563 }
564 !self.default_value.lock().is(&vm.ctx.typing_no_default)
565 }
566
567 #[pymethod]
568 fn __typing_subst__(
569 zelf: crate::PyRef<Self>,
570 arg: PyObjectRef,
571 vm: &VirtualMachine,
572 ) -> PyResult {
573 let self_obj: PyObjectRef = zelf.into();
574 call_typing_func_object(vm, "_paramspec_subst", (self_obj, arg))
575 }
576
577 #[pymethod]
578 fn __typing_prepare_subst__(
579 zelf: crate::PyRef<Self>,
580 alias: PyObjectRef,
581 args: PyObjectRef,
582 vm: &VirtualMachine,
583 ) -> PyResult {
584 let self_obj: PyObjectRef = zelf.into();
585 call_typing_func_object(vm, "_paramspec_prepare_subst", (self_obj, alias, args))
586 }
587 }
588
589 impl AsNumber for ParamSpec {
590 fn as_number() -> &'static PyNumberMethods {
591 static AS_NUMBER: PyNumberMethods = PyNumberMethods {
592 or: Some(|a, b, vm| {
593 let args = PyTuple::new_ref(vec![a.to_owned(), b.to_owned()], &vm.ctx);
594 make_union(&args, vm)
595 }),
596 ..PyNumberMethods::NOT_IMPLEMENTED
597 };
598 &AS_NUMBER
599 }
600 }
601
602 impl Constructor for ParamSpec {
603 type Args = FuncArgs;
604
605 fn slot_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
606 let mut kwargs = args.kwargs;
607 let name = if args.args.is_empty() {
609 if let Some(name) = kwargs.swap_remove("name") {
611 name
612 } else {
613 return Err(
614 vm.new_type_error("ParamSpec() missing required argument: 'name' (pos 1)")
615 );
616 }
617 } else if args.args.len() == 1 {
618 args.args[0].clone()
619 } else {
620 return Err(vm.new_type_error("ParamSpec() takes at most 1 positional argument"));
621 };
622
623 let bound = kwargs
624 .swap_remove("bound")
625 .map(|b| type_check(b, "Bound must be a type.", vm))
626 .transpose()?;
627 let covariant = kwargs
628 .swap_remove("covariant")
629 .map(|v| v.try_to_bool(vm))
630 .transpose()?
631 .unwrap_or(false);
632 let contravariant = kwargs
633 .swap_remove("contravariant")
634 .map(|v| v.try_to_bool(vm))
635 .transpose()?
636 .unwrap_or(false);
637 let infer_variance = kwargs
638 .swap_remove("infer_variance")
639 .map(|v| v.try_to_bool(vm))
640 .transpose()?
641 .unwrap_or(false);
642 let default = kwargs.swap_remove("default");
643
644 if !kwargs.is_empty() {
646 let unexpected_keys: Vec<String> = kwargs.keys().map(|s| s.to_string()).collect();
647 return Err(vm.new_type_error(format!(
648 "ParamSpec() got unexpected keyword argument(s): {}",
649 unexpected_keys.join(", ")
650 )));
651 }
652
653 if covariant && contravariant {
655 return Err(vm.new_value_error("Bivariant type variables are not supported."));
656 }
657
658 if infer_variance && (covariant || contravariant) {
659 return Err(vm.new_value_error("Variance cannot be specified with infer_variance"));
660 }
661
662 let default_value = default.unwrap_or_else(|| vm.ctx.typing_no_default.clone().into());
664
665 let paramspec = Self {
666 name,
667 bound,
668 default_value: PyMutex::new(default_value),
669 evaluate_default: PyMutex::new(vm.ctx.none()),
670 covariant,
671 contravariant,
672 infer_variance,
673 };
674
675 let obj = paramspec.into_ref_with_type(vm, cls)?;
676 let obj_ref: PyObjectRef = obj.into();
677 set_module_from_caller(&obj_ref, vm)?;
678 Ok(obj_ref)
679 }
680
681 fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
682 unimplemented!("use slot_new")
683 }
684 }
685
686 impl Representable for ParamSpec {
687 #[inline(always)]
688 fn repr_str(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
689 let name = zelf.__name__().str_utf8(vm)?;
690 Ok(variance_repr(
691 name.as_str(),
692 zelf.infer_variance,
693 zelf.covariant,
694 zelf.contravariant,
695 ))
696 }
697 }
698
699 impl ParamSpec {
700 pub fn new(name: PyObjectRef, vm: &VirtualMachine) -> Self {
701 Self {
702 name,
703 bound: None,
704 default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
705 evaluate_default: PyMutex::new(vm.ctx.none()),
706 covariant: false,
707 contravariant: false,
708 infer_variance: true,
709 }
710 }
711 }
712
713 #[pyattr]
714 #[pyclass(name = "TypeVarTuple", module = "typing")]
715 #[derive(Debug, PyPayload)]
716 #[allow(dead_code)]
717 pub struct TypeVarTuple {
718 name: PyObjectRef,
719 default_value: PyMutex<PyObjectRef>,
720 evaluate_default: PyMutex<PyObjectRef>,
721 }
722 #[pyclass(
723 flags(HAS_DICT, HAS_WEAKREF),
724 with(Constructor, Representable, Iterable)
725 )]
726 impl TypeVarTuple {
727 #[pygetset]
728 fn __name__(&self) -> PyObjectRef {
729 self.name.clone()
730 }
731
732 #[pygetset]
733 fn __default__(&self, vm: &VirtualMachine) -> PyResult {
734 {
735 let default_value = self.default_value.lock();
736 if !default_value.is(&vm.ctx.typing_no_default) {
737 return Ok(default_value.clone());
738 }
739 }
740 let evaluator = self.evaluate_default.lock().clone();
741 if !vm.is_none(&evaluator) {
742 let result = evaluator.call((1i32,), vm)?;
743 *self.default_value.lock() = result.clone();
744 Ok(result)
745 } else {
746 Ok(vm.ctx.typing_no_default.clone().into())
747 }
748 }
749
750 #[pygetset]
751 fn evaluate_default(&self, vm: &VirtualMachine) -> PyResult {
752 let evaluator = self.evaluate_default.lock().clone();
753 if !vm.is_none(&evaluator) {
754 return Ok(evaluator);
755 }
756 let default_value = self.default_value.lock().clone();
757 if !default_value.is(&vm.ctx.typing_no_default) {
758 return Ok(const_evaluator_alloc(default_value, vm));
759 }
760 Ok(vm.ctx.none())
761 }
762
763 #[pymethod]
764 fn has_default(&self, vm: &VirtualMachine) -> bool {
765 if !vm.is_none(&self.evaluate_default.lock()) {
766 return true;
767 }
768 let default_value = self.default_value.lock();
769 !default_value.is(&vm.ctx.typing_no_default)
770 }
771
772 #[pymethod]
773 fn __reduce__(&self) -> PyObjectRef {
774 self.name.clone()
775 }
776
777 #[pymethod]
778 fn __mro_entries__(&self, _bases: PyObjectRef, vm: &VirtualMachine) -> PyResult {
779 Err(vm.new_type_error("Cannot subclass an instance of TypeVarTuple"))
780 }
781
782 #[pymethod]
783 fn __typing_subst__(&self, _arg: PyObjectRef, vm: &VirtualMachine) -> PyResult {
784 Err(vm.new_type_error("Substitution of bare TypeVarTuple is not supported"))
785 }
786
787 #[pymethod]
788 fn __typing_prepare_subst__(
789 zelf: crate::PyRef<Self>,
790 alias: PyObjectRef,
791 args: PyObjectRef,
792 vm: &VirtualMachine,
793 ) -> PyResult {
794 let self_obj: PyObjectRef = zelf.into();
795 call_typing_func_object(vm, "_typevartuple_prepare_subst", (self_obj, alias, args))
796 }
797 }
798
799 impl Iterable for TypeVarTuple {
800 fn iter(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
801 let typing = vm.import("typing", 0)?;
804 let unpack = typing.get_attr("Unpack", vm)?;
805 let zelf_obj: PyObjectRef = zelf.into();
806 let unpacked = vm.call_method(&unpack, "__getitem__", (zelf_obj,))?;
807 let list = vm.ctx.new_list(vec![unpacked]);
808 let list_obj: PyObjectRef = list.into();
809 vm.call_method(&list_obj, "__iter__", ())
810 }
811 }
812
813 impl Constructor for TypeVarTuple {
814 type Args = FuncArgs;
815
816 fn slot_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult {
817 let mut kwargs = args.kwargs;
818 let name = if args.args.is_empty() {
820 if let Some(name) = kwargs.swap_remove("name") {
822 name
823 } else {
824 return Err(vm.new_type_error(
825 "TypeVarTuple() missing required argument: 'name' (pos 1)",
826 ));
827 }
828 } else if args.args.len() == 1 {
829 args.args[0].clone()
830 } else {
831 return Err(vm.new_type_error("TypeVarTuple() takes at most 1 positional argument"));
832 };
833
834 let default = kwargs.swap_remove("default");
835
836 if !kwargs.is_empty() {
838 let unexpected_keys: Vec<String> = kwargs.keys().map(|s| s.to_string()).collect();
839 return Err(vm.new_type_error(format!(
840 "TypeVarTuple() got unexpected keyword argument(s): {}",
841 unexpected_keys.join(", ")
842 )));
843 }
844
845 let (default_value, evaluate_default) = if let Some(default) = default {
847 (default, vm.ctx.none())
848 } else {
849 (vm.ctx.typing_no_default.clone().into(), vm.ctx.none())
851 };
852
853 let typevartuple = Self {
854 name,
855 default_value: PyMutex::new(default_value),
856 evaluate_default: PyMutex::new(evaluate_default),
857 };
858
859 let obj = typevartuple.into_ref_with_type(vm, cls)?;
860 let obj_ref: PyObjectRef = obj.into();
861 set_module_from_caller(&obj_ref, vm)?;
862 Ok(obj_ref)
863 }
864
865 fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
866 unimplemented!("use slot_new")
867 }
868 }
869
870 impl Representable for TypeVarTuple {
871 #[inline(always)]
872 fn repr_str(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
873 let name = zelf.name.str(vm)?;
874 Ok(name.to_string())
875 }
876 }
877
878 impl TypeVarTuple {
879 pub fn new(name: PyObjectRef, vm: &VirtualMachine) -> Self {
880 Self {
881 name,
882 default_value: PyMutex::new(vm.ctx.typing_no_default.clone().into()),
883 evaluate_default: PyMutex::new(vm.ctx.none()),
884 }
885 }
886 }
887
888 #[pyattr]
889 #[pyclass(name = "ParamSpecArgs", module = "typing")]
890 #[derive(Debug, PyPayload)]
891 #[allow(dead_code)]
892 pub struct ParamSpecArgs {
893 __origin__: PyObjectRef,
894 }
895 #[pyclass(with(Constructor, Representable, Comparable), flags(HAS_WEAKREF))]
896 impl ParamSpecArgs {
897 #[pymethod]
898 fn __mro_entries__(&self, _bases: PyObjectRef, vm: &VirtualMachine) -> PyResult {
899 Err(vm.new_type_error("Cannot subclass an instance of ParamSpecArgs"))
900 }
901
902 #[pygetset]
903 fn __origin__(&self) -> PyObjectRef {
904 self.__origin__.clone()
905 }
906 }
907
908 impl Constructor for ParamSpecArgs {
909 type Args = (PyObjectRef,);
910
911 fn py_new(_cls: &Py<PyType>, args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
912 let origin = args.0;
913 Ok(Self { __origin__: origin })
914 }
915 }
916
917 impl Representable for ParamSpecArgs {
918 #[inline(always)]
919 fn repr_str(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
920 if let Ok(name) = zelf.__origin__.get_attr("__name__", vm) {
922 return Ok(format!("{name}.args", name = name.str(vm)?));
923 }
924 Ok(format!("{:?}.args", zelf.__origin__))
925 }
926 }
927
928 impl Comparable for ParamSpecArgs {
929 fn cmp(
930 zelf: &crate::Py<Self>,
931 other: &PyObject,
932 op: PyComparisonOp,
933 vm: &VirtualMachine,
934 ) -> PyResult<PyComparisonValue> {
935 op.eq_only(|| {
936 if other.class().is(zelf.class())
937 && let Some(other_args) = other.downcast_ref::<ParamSpecArgs>()
938 {
939 let eq = zelf.__origin__.rich_compare_bool(
940 &other_args.__origin__,
941 PyComparisonOp::Eq,
942 vm,
943 )?;
944 return Ok(PyComparisonValue::Implemented(eq));
945 }
946 Ok(PyComparisonValue::NotImplemented)
947 })
948 }
949 }
950
951 #[pyattr]
952 #[pyclass(name = "ParamSpecKwargs", module = "typing")]
953 #[derive(Debug, PyPayload)]
954 #[allow(dead_code)]
955 pub struct ParamSpecKwargs {
956 __origin__: PyObjectRef,
957 }
958 #[pyclass(with(Constructor, Representable, Comparable), flags(HAS_WEAKREF))]
959 impl ParamSpecKwargs {
960 #[pymethod]
961 fn __mro_entries__(&self, _bases: PyObjectRef, vm: &VirtualMachine) -> PyResult {
962 Err(vm.new_type_error("Cannot subclass an instance of ParamSpecKwargs"))
963 }
964
965 #[pygetset]
966 fn __origin__(&self) -> PyObjectRef {
967 self.__origin__.clone()
968 }
969 }
970
971 impl Constructor for ParamSpecKwargs {
972 type Args = (PyObjectRef,);
973
974 fn py_new(_cls: &Py<PyType>, args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
975 let origin = args.0;
976 Ok(Self { __origin__: origin })
977 }
978 }
979
980 impl Representable for ParamSpecKwargs {
981 #[inline(always)]
982 fn repr_str(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
983 if let Ok(name) = zelf.__origin__.get_attr("__name__", vm) {
985 return Ok(format!("{name}.kwargs", name = name.str(vm)?));
986 }
987 Ok(format!("{:?}.kwargs", zelf.__origin__))
988 }
989 }
990
991 impl Comparable for ParamSpecKwargs {
992 fn cmp(
993 zelf: &crate::Py<Self>,
994 other: &PyObject,
995 op: PyComparisonOp,
996 vm: &VirtualMachine,
997 ) -> PyResult<PyComparisonValue> {
998 op.eq_only(|| {
999 if other.class().is(zelf.class())
1000 && let Some(other_kwargs) = other.downcast_ref::<ParamSpecKwargs>()
1001 {
1002 let eq = zelf.__origin__.rich_compare_bool(
1003 &other_kwargs.__origin__,
1004 PyComparisonOp::Eq,
1005 vm,
1006 )?;
1007 return Ok(PyComparisonValue::Implemented(eq));
1008 }
1009 Ok(PyComparisonValue::NotImplemented)
1010 })
1011 }
1012 }
1013
1014 fn call_typing_args_kwargs(
1017 name: &'static str,
1018 cls: PyTypeRef,
1019 args: FuncArgs,
1020 vm: &VirtualMachine,
1021 ) -> PyResult {
1022 let typing = vm.import("typing", 0)?;
1023 let func = typing.get_attr(name, vm)?;
1024
1025 let mut call_args = vec![cls.into()];
1027 call_args.extend(args.args);
1028
1029 let func_args = FuncArgs {
1031 args: call_args,
1032 kwargs: args.kwargs,
1033 };
1034
1035 func.call(func_args, vm)
1036 }
1037
1038 #[pyattr]
1039 #[pyclass(name = "Generic", module = "typing")]
1040 #[derive(Debug, PyPayload)]
1041 #[allow(dead_code)]
1042 pub struct Generic;
1043
1044 #[pyclass(flags(BASETYPE, HEAPTYPE))]
1045 impl Generic {
1046 #[pyattr]
1047 fn __slots__(ctx: &Context) -> PyTupleRef {
1048 ctx.empty_tuple.clone()
1049 }
1050
1051 #[pyclassmethod]
1052 fn __class_getitem__(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
1053 call_typing_args_kwargs("_generic_class_getitem", cls, args, vm)
1054 }
1055
1056 #[pyclassmethod]
1057 fn __init_subclass__(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
1058 call_typing_args_kwargs("_generic_init_subclass", cls, args, vm)
1059 }
1060 }
1061
1062 pub fn set_typeparam_default(
1065 type_param: PyObjectRef,
1066 evaluate_default: PyObjectRef,
1067 vm: &VirtualMachine,
1068 ) -> PyResult {
1069 fn try_set_default<T>(
1071 obj: &PyObject,
1072 evaluate_default: &PyObject,
1073 get_field: impl FnOnce(&T) -> &PyMutex<PyObjectRef>,
1074 ) -> bool
1075 where
1076 T: PyPayload,
1077 {
1078 if let Some(typed_obj) = obj.downcast_ref::<T>() {
1079 *get_field(typed_obj).lock() = evaluate_default.to_owned();
1080 true
1081 } else {
1082 false
1083 }
1084 }
1085
1086 if try_set_default::<TypeVar>(&type_param, &evaluate_default, |tv| &tv.evaluate_default)
1088 || try_set_default::<ParamSpec>(&type_param, &evaluate_default, |ps| {
1089 &ps.evaluate_default
1090 })
1091 || try_set_default::<TypeVarTuple>(&type_param, &evaluate_default, |tvt| {
1092 &tvt.evaluate_default
1093 })
1094 {
1095 Ok(type_param)
1096 } else {
1097 Err(vm.new_type_error(format!(
1098 "Expected a type param, got {}",
1099 type_param.class().name()
1100 )))
1101 }
1102 }
1103}