Skip to content

Commit cb6c570

Browse files
Fix error with null=True and Any type param for Field types (#2492)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 27bb147 commit cb6c570

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

mypy_django_plugin/transformers/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ def set_descriptor_types_for_field(
166166
if not (isinstance(mapped_set_type, UninhabitedType) or isinstance(mapped_get_type, UninhabitedType)):
167167
# always replace set_type and get_type with (non-Any) mapped types
168168
set_type = helpers.convert_any_to_type(mapped_set_type, set_type)
169-
get_type = helpers.convert_any_to_type(mapped_get_type, get_type)
169+
get_type = get_proper_type(helpers.convert_any_to_type(mapped_get_type, get_type))
170170

171171
# the get_type must be optional if the field is nullable
172172
if (is_get_nullable or is_nullable) and not (
173-
isinstance(get_proper_type(get_type), NoneType) or helpers.is_optional(get_type)
173+
isinstance(get_type, NoneType) or helpers.is_optional(get_type) or isinstance(get_type, AnyType)
174174
):
175175
ctx.api.fail(
176176
f"{default_return_type.type.name} is nullable but its generic get type parameter is not optional",

tests/typecheck/fields/test_custom_fields.yml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@
1818
reveal_type(user.my_custom_field13) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]"
1919
reveal_type(user.my_custom_field14) # N: Revealed type is "Union[builtins.bool, None]"
2020
reveal_type(user.my_custom_field15) # N: Revealed type is "None"
21+
22+
reveal_type(user.my_custom_field_any1) # N: Revealed type is "Any"
23+
reveal_type(user.my_custom_field_any2) # N: Revealed type is "Any"
24+
reveal_type(user.my_custom_field_any3) # N: Revealed type is "Any"
25+
reveal_type(user.my_custom_field_any4) # N: Revealed type is "Any"
2126
monkeypatch: true
22-
out: |
23-
myapp/models:31: error: GenericField is nullable but its generic get type parameter is not optional [misc]
24-
myapp/models:32: error: CustomValueField is nullable but its generic get type parameter is not optional [misc]
25-
myapp/models:33: error: SingleTypeField is nullable but its generic get type parameter is not optional [misc]
26-
myapp/models:34: error: AdditionalTypeVarField is nullable but its generic get type parameter is not optional [misc]
27-
myapp/models:35: error: Field is nullable but its generic get type parameter is not optional [misc]
2827
installed_apps:
2928
- myapp
3029
files:
@@ -53,19 +52,24 @@
5352
5453
class CustomSmallIntegerField(fields.SmallIntegerField[_ST, _GT]): ...
5554
55+
class FieldImplicitAny(fields.Field): ...
56+
class FieldExplicitAny(fields.Field[Any, Any]): ...
57+
5658
class User(models.Model):
5759
id = models.AutoField(primary_key=True)
5860
my_custom_field1 = GenericField[Union[CustomFieldValue, int], CustomFieldValue]()
5961
my_custom_field2 = CustomValueField()
6062
my_custom_field3 = SingleTypeField[bool]()
6163
my_custom_field4 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool]()
64+
my_custom_field_any1 = FieldImplicitAny()
65+
my_custom_field_any2 = FieldExplicitAny()
6266
6367
# test null=True on fields with non-optional generic types throw error
64-
my_custom_field5 = GenericField[Union[CustomFieldValue, int], CustomFieldValue](null=True)
65-
my_custom_field6 = CustomValueField(null=True)
66-
my_custom_field7 = SingleTypeField[bool](null=True)
67-
my_custom_field8 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool](null=True)
68-
my_custom_field9 = fields.Field[Union[CustomFieldValue, int], CustomFieldValue](null=True)
68+
my_custom_field5 = GenericField[Union[CustomFieldValue, int], CustomFieldValue](null=True) # E: GenericField is nullable but its generic get type parameter is not optional [misc]
69+
my_custom_field6 = CustomValueField(null=True) # E: CustomValueField is nullable but its generic get type parameter is not optional [misc]
70+
my_custom_field7 = SingleTypeField[bool](null=True) # E: SingleTypeField is nullable but its generic get type parameter is not optional [misc]
71+
my_custom_field8 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool](null=True) # E: AdditionalTypeVarField is nullable but its generic get type parameter is not optional [misc]
72+
my_custom_field9 = fields.Field[Union[CustomFieldValue, int], CustomFieldValue](null=True) # E: Field is nullable but its generic get type parameter is not optional [misc]
6973
7074
# test overriding fields that set _pyi_private_set_type or _pyi_private_get_type
7175
my_custom_field10 = fields.SmallIntegerField[bool, bool]()
@@ -76,3 +80,7 @@
7680
my_custom_field13 = GenericField[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True)
7781
my_custom_field14 = SingleTypeField[Union[bool, None]](null=True)
7882
my_custom_field15 = fields.Field[None, None](null=True)
83+
84+
# test null=True on Any does not raise
85+
my_custom_field_any3 = FieldImplicitAny(null=True)
86+
my_custom_field_any4 = FieldExplicitAny(null=True)

0 commit comments

Comments
 (0)