diff --git a/mypy_django_plugin/transformers/fields.py b/mypy_django_plugin/transformers/fields.py index f2bd21009..0a1f1c435 100644 --- a/mypy_django_plugin/transformers/fields.py +++ b/mypy_django_plugin/transformers/fields.py @@ -166,11 +166,11 @@ def set_descriptor_types_for_field( if not (isinstance(mapped_set_type, UninhabitedType) or isinstance(mapped_get_type, UninhabitedType)): # always replace set_type and get_type with (non-Any) mapped types set_type = helpers.convert_any_to_type(mapped_set_type, set_type) - get_type = helpers.convert_any_to_type(mapped_get_type, get_type) + get_type = get_proper_type(helpers.convert_any_to_type(mapped_get_type, get_type)) # the get_type must be optional if the field is nullable if (is_get_nullable or is_nullable) and not ( - isinstance(get_proper_type(get_type), NoneType) or helpers.is_optional(get_type) + isinstance(get_type, NoneType) or helpers.is_optional(get_type) or isinstance(get_type, AnyType) ): ctx.api.fail( f"{default_return_type.type.name} is nullable but its generic get type parameter is not optional", diff --git a/tests/typecheck/fields/test_custom_fields.yml b/tests/typecheck/fields/test_custom_fields.yml index 14d175348..335de9a55 100644 --- a/tests/typecheck/fields/test_custom_fields.yml +++ b/tests/typecheck/fields/test_custom_fields.yml @@ -18,13 +18,12 @@ reveal_type(user.my_custom_field13) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" reveal_type(user.my_custom_field14) # N: Revealed type is "Union[builtins.bool, None]" reveal_type(user.my_custom_field15) # N: Revealed type is "None" + + reveal_type(user.my_custom_field_any1) # N: Revealed type is "Any" + reveal_type(user.my_custom_field_any2) # N: Revealed type is "Any" + reveal_type(user.my_custom_field_any3) # N: Revealed type is "Any" + reveal_type(user.my_custom_field_any4) # N: Revealed type is "Any" monkeypatch: true - out: | - myapp/models:31: error: GenericField is nullable but its generic get type parameter is not optional [misc] - myapp/models:32: error: CustomValueField is nullable but its generic get type parameter is not optional [misc] - myapp/models:33: error: SingleTypeField is nullable but its generic get type parameter is not optional [misc] - myapp/models:34: error: AdditionalTypeVarField is nullable but its generic get type parameter is not optional [misc] - myapp/models:35: error: Field is nullable but its generic get type parameter is not optional [misc] installed_apps: - myapp files: @@ -53,19 +52,24 @@ class CustomSmallIntegerField(fields.SmallIntegerField[_ST, _GT]): ... + class FieldImplicitAny(fields.Field): ... + class FieldExplicitAny(fields.Field[Any, Any]): ... + class User(models.Model): id = models.AutoField(primary_key=True) my_custom_field1 = GenericField[Union[CustomFieldValue, int], CustomFieldValue]() my_custom_field2 = CustomValueField() my_custom_field3 = SingleTypeField[bool]() my_custom_field4 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool]() + my_custom_field_any1 = FieldImplicitAny() + my_custom_field_any2 = FieldExplicitAny() # test null=True on fields with non-optional generic types throw error - my_custom_field5 = GenericField[Union[CustomFieldValue, int], CustomFieldValue](null=True) - my_custom_field6 = CustomValueField(null=True) - my_custom_field7 = SingleTypeField[bool](null=True) - my_custom_field8 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool](null=True) - my_custom_field9 = fields.Field[Union[CustomFieldValue, int], CustomFieldValue](null=True) + my_custom_field5 = GenericField[Union[CustomFieldValue, int], CustomFieldValue](null=True) # E: GenericField is nullable but its generic get type parameter is not optional [misc] + my_custom_field6 = CustomValueField(null=True) # E: CustomValueField is nullable but its generic get type parameter is not optional [misc] + my_custom_field7 = SingleTypeField[bool](null=True) # E: SingleTypeField is nullable but its generic get type parameter is not optional [misc] + 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] + 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] # test overriding fields that set _pyi_private_set_type or _pyi_private_get_type my_custom_field10 = fields.SmallIntegerField[bool, bool]() @@ -76,3 +80,7 @@ my_custom_field13 = GenericField[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True) my_custom_field14 = SingleTypeField[Union[bool, None]](null=True) my_custom_field15 = fields.Field[None, None](null=True) + + # test null=True on Any does not raise + my_custom_field_any3 = FieldImplicitAny(null=True) + my_custom_field_any4 = FieldExplicitAny(null=True)