django-stubs: Type from settings not correctly loaded in a model

Bug report

I have this in settings:

BANK_ENTITIES = [('a', 'A Bank'), ('b', 'B Bank'),]

and this in my model:

entity = models.CharField(max_length=20, choices=settings.BANK_ENTITIES, blank=True)

What’s wrong

mypy fails with:

models.py:247: error: Argument "choices" to "CharField" has incompatible type "tuple"; expected "Optional[Iterable[Union[Tuple[Any, Any], Tuple[str, Iterable[Tuple[Any, Any]]]]]]"

If I place a reveal in settings and another in models.py I get

settingsbase.py:90: note: Revealed type is 'builtins.list[Tuple[builtins.str, builtins.str]]'
models.py:214: note: Revealed type is 'builtins.list'

How is that should be

mypy should be able to load the full type from settings, not only that it’s a list

System information

  • OS: Ubuntu 18.04
  • python version: 3.6
  • django version: 2.2
  • mypy version: 0.761
  • django-stubs version: 1.4.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 22 (15 by maintainers)

Commits related to this issue

Most upvoted comments

Any chance to move this issue forward? Configuration keeps producing quite a lot of warnings and it is a bit difficult to work around it.

Hello, I have the same issue, I tried to understand why it happens. In this function, plugin cant extract type from sym variable, because it’s dict variable? after that, the plugin tries to understand what`s type, based on the variable value. https://github.com/typeddjango/django-stubs/blob/9a95b983981173d86b55c3ede97f637d94cfde9e/mypy_django_plugin/transformers/settings.py#L23-L49 In the case with dict value, the plugin gets type from builtins module. https://github.com/python/mypy/blob/master/mypy/typeshed/stdlib/builtins.pyi#L788

class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]):

I think, the plugin needs to check if its dict and return dict type from mypy module, like

Dict[Any, Any]

If it’s the good solution I will make PR.

I think I have a related issue

# settings.py
SOME_DICT = {
    'a': 'whatever',
    'b': 'whatever',
    'c': 'whatever',
}
# myproject/mymodule.py
from django.conf import settings

whatever = settings.SOME_DICT["b"]

and mypy gives the following error:

myproject/mymodule.py:3: error: Invalid index type "str" for "dict"; expected type "_KT"

The _KT TypeVar appears to be defined in mypy typeshed in relation to Mapping container, i.e. for dicts

Adding an annotation to the settings like this does not help:

# settings.py
from typing import Dict

SOME_DICT: Dict[str, str] = {
    'a': 'whatever',
    'b': 'whatever',
    'c': 'whatever',
}

The problem is that my settings import different sub modules for settings depending on the country that was configured.

we also have similar situation with conditional import of sub-module settings, maybe is relevant

(my example code above is simplified so might not reproduce the issue by itself)

I am able to make mypy happy with the following workaround:

# myproject/mymodule.py
from typing import Dict
from django.conf import settings

_some_dict: Dict[str, str] = settings.SOME_DICT

whatever = _some_dict["b"]

(and no annotation in settings.py)