Type definition for Field.__set__ does not expect None to be passed even if the field is nullable
Describe the bug
Trying to assign None to a field that has null=True gives a type error.
To Reproduce
import tortoise
from tortoise import fields
class Test(tortoise.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255, null=True)
a = Test(name="test")
a.name = None
Resulting type checks:
git:(main) ✗ uv run mypy .
test.py:12: error: Incompatible types in assignment (expression has type "None", variable has type "str") [assignment]
Found 1 error in 1 file (checked 2 source files)
git:(main) ✗ uv run pyright .
/Users/zw/Development/tortoise-typebug/test.py
/Users/zw/Development/tortoise-typebug/test.py:12:3 - error: Cannot assign to attribute "name" for class "Test"
Argument of type "None" cannot be assigned to parameter "value" of type "str" in function "__set__"
"None" is not assignable to "str" (reportAttributeAccessIssue)
1 error, 0 warnings, 0 informations
Expected behavior Should be allowed to set a field to None. It's a legal value and the type definition should reflect this. Additional context Happy to help out with a PR if needed. Would appreciate some pointers.
https://github.com/tortoise/tortoise-orm/blob/develop/tortoise/fields/base.py#L165
Here's the problematic code. This is causing an issue because CharField is defined as follows:
class CharField(Field[str]):
...
I'm also including my current workaround which works but requires lot of copypaste boilerplate.
class RequiredUUIDField(fields.UUIDField):
def __set__(self, instance: "Model", value: uuid.UUID) -> None:
super().__set__(instance, value)
class NullableUUIDField(fields.UUIDField):
def __set__(self, instance: "Model", value: Optional[uuid.UUID]) -> None:
super().__set__(instance, value) # type: ignore
@overload
def UUIDField(null: Literal[False] = False, **kwargs) -> RequiredUUIDField: ...
@overload
def UUIDField(null: Literal[True], **kwargs) -> NullableUUIDField: ...
def UUIDField(null: bool = False, **kwargs):
if null:
return NullableUUIDField(null=True, **kwargs)
return RequiredUUIDField(**kwargs)
any update on this ? (is this planned ?) and if as the same time other type-hint issue could be fix like :
- Type of "get_or_create" is partially unknown
- "Meta" overrides symbol of same name in class "Model"
- The values_list returning a tuple even tho flat is True
- (i have others if needed) that would be incredible !
Offtopic, but for Meta, you can fix the type error by importing and subclassing the parent Meta in your models.
Offtopic, but for Meta, you can fix the type error by importing and subclassing the parent Meta in your models.
both of them are related to strict typeing and i think that if a pr is made, its gonna fix all of the type hint issue and not only 1 Thanks tho