1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
- case: test_model_fields_classes_present_as_primitives
main: |
from typing_extensions import reveal_type
from myapp.models import User
user = User(small_int=1, name='user', slug='user', text='user')
reveal_type(user.id) # N: Revealed type is "builtins.int"
reveal_type(user.small_int) # N: Revealed type is "builtins.int"
reveal_type(user.name) # N: Revealed type is "builtins.str"
reveal_type(user.slug) # N: Revealed type is "builtins.str"
reveal_type(user.text) # N: Revealed type is "builtins.str"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class User(models.Model):
id = models.AutoField(primary_key=True)
small_int = models.SmallIntegerField()
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
text = models.TextField()
- case: test_model_field_classes_from_existing_locations
main: |
from typing_extensions import reveal_type
from myapp.models import Booking
booking = Booking()
reveal_type(booking.id) # N: Revealed type is "builtins.int"
reveal_type(booking.time_range) # N: Revealed type is "Any"
reveal_type(booking.some_decimal) # N: Revealed type is "decimal.Decimal"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
from django.contrib.postgres import fields as pg_fields
from decimal import Decimal
class Booking(models.Model):
id = models.AutoField(primary_key=True)
time_range = pg_fields.DateTimeRangeField(null=False)
some_decimal = models.DecimalField(max_digits=10, decimal_places=5)
- case: test_add_id_field_if_no_primary_key_defined
disable_cache: true
main: |
from typing_extensions import reveal_type
from myapp.models import User
reveal_type(User().id) # N: Revealed type is "builtins.int"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class User(models.Model):
pass
- case: test_do_not_add_id_if_field_with_primary_key_True_defined
disable_cache: true
main: |
from typing_extensions import reveal_type
from myapp.models import User
reveal_type(User().my_pk) # N: Revealed type is "builtins.int"
User().id # E: "User" has no attribute "id" [attr-defined]
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class User(models.Model):
my_pk = models.IntegerField(primary_key=True)
- case: blank_and_null_char_field_allows_none
main: |
from typing_extensions import reveal_type
from myapp.models import MyModel
MyModel(nulltext="")
MyModel(nulltext=None)
MyModel().nulltext=None
reveal_type(MyModel().nulltext) # N: Revealed type is "builtins.str | None"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class MyModel(models.Model):
nulltext=models.CharField(max_length=1, blank=True, null=True)
- case: blank_and_not_null_charfield_does_not_allow_none
main: |
from typing_extensions import reveal_type
from myapp.models import MyModel
MyModel(notnulltext=None) # E: Incompatible type for "notnulltext" of "MyModel" (got "None", expected "str | int | Combinable") [misc]
MyModel(notnulltext="")
MyModel().notnulltext = None # E: Incompatible types in assignment (expression has type "None", variable has type "str | int | Combinable") [assignment]
reveal_type(MyModel().notnulltext) # N: Revealed type is "builtins.str"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class MyModel(models.Model):
notnulltext=models.CharField(max_length=1, blank=True, null=False)
- case: if_field_called_on_class_return_field_itself
main: |
from typing_extensions import reveal_type
from myapp.models import MyUser
reveal_type(MyUser.name.field) # N: Revealed type is "django.db.models.fields.CharField[builtins.str | builtins.int | django.db.models.expressions.Combinable, builtins.str]"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class MyUser(models.Model):
name = models.CharField(max_length=100)
- case: fields_on_non_model_classes_resolve_to_field_type
main: |
from typing_extensions import reveal_type
from django.db import models
class MyClass:
myfield: models.IntegerField[int, int]
reveal_type(MyClass.myfield) # N: Revealed type is "django.db.models.fields._FieldDescriptor[django.db.models.fields.IntegerField[builtins.int, builtins.int]]"
reveal_type(MyClass.myfield.field) # N: Revealed type is "django.db.models.fields.IntegerField[builtins.int, builtins.int]"
reveal_type(MyClass().myfield) # N: Revealed type is "django.db.models.fields.IntegerField[builtins.int, builtins.int]"
- case: fields_inside_mixins_used_in_model_subclasses_resolved_as_primitives
main: |
from typing_extensions import reveal_type
from myapp.models import MyModel, AuthMixin
reveal_type(MyModel().username) # N: Revealed type is "builtins.str"
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class AuthMixin(models.Model):
class Meta:
abstract = True
username = models.CharField(max_length=100)
class MyModel(AuthMixin, models.Model):
pass
- case: can_narrow_field_type
main: |
from typing import cast, NewType
from typing_extensions import reveal_type
from django.db import models
Year = NewType("Year", int)
class Book(models.Model):
published = cast(models.Field[Year, Year], models.IntegerField())
book = Book()
reveal_type(book.published) # N: Revealed type is "main.Year"
book.published = 2006 # E: Incompatible types in assignment (expression has type "int", variable has type "Year") [assignment]
book.published = Year(2006)
reveal_type(book.published) # N: Revealed type is "main.Year"
def accepts_int(arg: int) -> None: ...
accepts_int(book.published)
- case: test_binary_field_return_types
main: |
from typing_extensions import reveal_type
from django.db import models
class EncodedMessage(models.Model):
message = models.BinaryField()
obj = EncodedMessage(b'\x010')
reveal_type(obj.message) # N: Revealed type is "builtins.bytes | builtins.memoryview[builtins.int]"
- case: test_small_auto_field_class_presents_as_int
main: |
from typing_extensions import reveal_type
from django.db import models
class MyModel(models.Model):
small = models.SmallAutoField(primary_key=True)
obj = MyModel()
reveal_type(obj.small) # N: Revealed type is "builtins.int"
- case: test_ignores_renamed_field
main: |
# Ref: https://github.com/typeddjango/django-stubs/issues/1261
# Django modifies the model so it doesn't have 'modelname', but we don't follow
# along. But the 'name=' argument to a field isn't a documented feature.
from typing_extensions import reveal_type
from myapp.models import RenamedField
instance = RenamedField()
reveal_type(instance.modelname) # N: Revealed type is "builtins.int"
instance.fieldname # E: "RenamedField" has no attribute "fieldname" [attr-defined]
instance.modelname = 1
instance.fieldname = 1 # E: "RenamedField" has no attribute "fieldname" [attr-defined]
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class RenamedField(models.Model):
modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),))
|