|
| 1 | +from collections.abc import Callable, Mapping, Sequence |
| 2 | +from typing import TypeVar |
| 3 | + |
| 4 | +from django.db import models |
| 5 | +from typing_extensions import assert_type |
| 6 | + |
| 7 | +_T = TypeVar("_T") |
| 8 | + |
| 9 | + |
| 10 | +def to_named_seq(func: Callable[[], _T]) -> Callable[[], Sequence[tuple[str, _T]]]: |
| 11 | + def inner() -> Sequence[tuple[str, _T]]: |
| 12 | + return [("title", func())] |
| 13 | + |
| 14 | + return inner |
| 15 | + |
| 16 | + |
| 17 | +def to_named_mapping(func: Callable[[], _T]) -> Callable[[], Mapping[str, _T]]: |
| 18 | + def inner() -> Mapping[str, _T]: |
| 19 | + return {"title": func()} |
| 20 | + |
| 21 | + return inner |
| 22 | + |
| 23 | + |
| 24 | +def str_tuple() -> Sequence[tuple[str, str]]: |
| 25 | + return (("foo", "bar"), ("fuzz", "bazz")) |
| 26 | + |
| 27 | + |
| 28 | +def str_mapping() -> Mapping[str, str]: |
| 29 | + return {"foo": "bar", "fuzz": "bazz"} |
| 30 | + |
| 31 | + |
| 32 | +def int_tuple() -> Sequence[tuple[int, str]]: |
| 33 | + return ((1, "bar"), (2, "bazz")) |
| 34 | + |
| 35 | + |
| 36 | +def int_mapping() -> Mapping[int, str]: |
| 37 | + return {3: "bar", 4: "bazz"} |
| 38 | + |
| 39 | + |
| 40 | +class TestModel(models.Model): |
| 41 | + class TextChoices(models.TextChoices): |
| 42 | + FIRST = "foo", "bar" |
| 43 | + SECOND = "foo2", "bar" |
| 44 | + |
| 45 | + class IntegerChoices(models.IntegerChoices): |
| 46 | + FIRST = 1, "bar" |
| 47 | + SECOND = 2, "bar" |
| 48 | + |
| 49 | + char1 = models.CharField[str, str](max_length=5, choices=TextChoices, default="foo") |
| 50 | + char2 = models.CharField[str, str](max_length=5, choices=str_tuple, default="foo") |
| 51 | + char3 = models.CharField[str, str](max_length=5, choices=str_mapping, default="foo") |
| 52 | + char4 = models.CharField[str, str](max_length=5, choices=str_tuple(), default="foo") |
| 53 | + char5 = models.CharField[str, str](max_length=5, choices=str_mapping(), default="foo") |
| 54 | + char6 = models.CharField[str, str](max_length=5, choices=to_named_seq(str_tuple), default="foo") |
| 55 | + char7 = models.CharField[str, str](max_length=5, choices=to_named_mapping(str_mapping), default="foo") |
| 56 | + char8 = models.CharField[str, str](max_length=5, choices=to_named_seq(str_tuple)(), default="foo") |
| 57 | + char9 = models.CharField[str, str](max_length=5, choices=to_named_mapping(str_mapping)(), default="foo") |
| 58 | + |
| 59 | + int1 = models.IntegerField[int, int](choices=IntegerChoices, default=1) |
| 60 | + int2 = models.IntegerField[int, int](choices=int_tuple, default=1) |
| 61 | + int3 = models.IntegerField[int, int](choices=int_mapping, default=1) |
| 62 | + int4 = models.IntegerField[int, int](choices=int_tuple(), default=1) |
| 63 | + int5 = models.IntegerField[int, int](choices=int_mapping(), default=1) |
| 64 | + int6 = models.IntegerField[int, int](choices=to_named_seq(int_tuple), default=1) |
| 65 | + int7 = models.IntegerField[int, int](choices=to_named_seq(int_mapping), default=1) |
| 66 | + int8 = models.IntegerField[int, int](choices=to_named_seq(int_tuple)(), default=1) |
| 67 | + int9 = models.IntegerField[int, int](choices=to_named_seq(int_mapping)(), default=1) |
| 68 | + |
| 69 | + |
| 70 | +instance = TestModel() |
| 71 | +assert_type(instance.char1, str) |
| 72 | +assert_type(instance.char2, str) |
| 73 | +assert_type(instance.char3, str) |
| 74 | +assert_type(instance.char4, str) |
| 75 | +assert_type(instance.char5, str) |
| 76 | +assert_type(instance.char6, str) |
| 77 | +assert_type(instance.char7, str) |
| 78 | +assert_type(instance.char8, str) |
| 79 | +assert_type(instance.char9, str) |
| 80 | + |
| 81 | +assert_type(instance.int1, int) |
| 82 | +assert_type(instance.int2, int) |
| 83 | +assert_type(instance.int3, int) |
| 84 | +assert_type(instance.int4, int) |
| 85 | +assert_type(instance.int5, int) |
| 86 | +assert_type(instance.int6, int) |
| 87 | +assert_type(instance.int7, int) |
| 88 | +assert_type(instance.int8, int) |
| 89 | +assert_type(instance.int9, int) |
0 commit comments