Skip to content

Commit

Permalink
[CHERRY-PICK] Suppress FieldDoesNotExist raised from attribute on c…
Browse files Browse the repository at this point in the history
…lass definition

If we've found an attribute on a model class that from all we can see
appears to be a field, but Django still raises `FieldDoesNotExist` we'll
suppress it.

This can appear if one uses the (undocumented) `Field(name=..., ...)`
argument.
  • Loading branch information
flaeppe authored and intgr committed Jan 23, 2023
1 parent 7ebd9db commit 556e914
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
7 changes: 5 additions & 2 deletions mypy_django_plugin/transformers/fields.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import TYPE_CHECKING, Any, Optional, Tuple, Union, cast

from django.core.exceptions import FieldDoesNotExist
from django.db.models.fields import AutoField, Field
from django.db.models.fields.related import RelatedField
from django.db.models.fields.reverse_related import ForeignObjectRel
Expand Down Expand Up @@ -38,8 +39,10 @@ def _get_current_field_from_assignment(
if model_cls is None:
return None

current_field = model_cls._meta.get_field(field_name)
return current_field
try:
return model_cls._meta.get_field(field_name)
except FieldDoesNotExist:
return None


def reparametrize_related_field_type(related_field_type: Instance, set_type: MypyType, get_type: MypyType) -> Instance:
Expand Down
21 changes: 21 additions & 0 deletions tests/typecheck/fields/test_base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,24 @@
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 myapp.models import RenamedField
instance = RenamedField()
reveal_type(instance.modelname) # N: Revealed type is "builtins.int"
instance.fieldname # E: "RenamedField" has no attribute "fieldname"
instance.modelname = 1
instance.fieldname = 1 # E: "RenamedField" has no attribute "fieldname"
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'),))

0 comments on commit 556e914

Please sign in to comment.