Coder Social home page Coder Social logo

django-stubs's Introduction

django-stubs

Build status Checked with mypy Gitter StackOverflow

This package contains type stubs and a custom mypy plugin to provide more precise static types and type inference for Django framework. Django uses some Python "magic" that makes having precise types for some code patterns problematic. This is why we need this project. The final goal is to be able to get precise types for most common patterns.

Installation

pip install 'django-stubs[compatible-mypy]'

To make mypy aware of the plugin, you need to add

[mypy]
plugins =
    mypy_django_plugin.main

[mypy.plugins.django-stubs]
django_settings_module = "myproject.settings"

in your mypy.ini or setup.cfg file.

pyproject.toml configurations are also supported:

[tool.mypy]
plugins = ["mypy_django_plugin.main"]

[tool.django-stubs]
django_settings_module = "myproject.settings"

Two things happening here:

  1. We need to explicitly list our plugin to be loaded by mypy
  2. You can either specify django_settings_module as seen above, or let django_stubs use the DJANGO_SETTINGS_MODULE variable from your environment.

This fully working typed boilerplate can serve you as an example.

Version compatibility

We rely on different django and mypy versions:

django-stubs Mypy version Django version Django partial support Python version
5.0.4 1.11.x 5.0 4.2 3.8 - 3.12
5.0.3 1.11.x 5.0 4.2 3.8 - 3.12
5.0.2 1.10.x 5.0 4.2 3.8 - 3.12
5.0.1 1.10.x 5.0 4.2 3.8 - 3.12
5.0.0 1.10.x 5.0 4.2, 4.1 3.8 - 3.12
4.2.7 1.7.x 4.2 4.1, 3.2 3.8 - 3.12
4.2.6 1.6.x 4.2 4.1, 3.2 3.8 - 3.12
4.2.5 1.6.x 4.2 4.1, 3.2 3.8 - 3.12
4.2.4 1.5.x 4.2 4.1, 3.2 3.8 - 3.11
4.2.3 1.4.x 4.2 4.1, 3.2 3.8 - 3.11
4.2.2 1.4.x 4.2 4.1, 3.2 3.8 - 3.11
4.2.1 1.3.x 4.2 4.1, 3.2 3.8 - 3.11
4.2.0 1.2.x 4.2 4.1, 4.0, 3.2 3.7 - 3.11
1.16.0 1.1.x 4.1 4.0, 3.2 3.7 - 3.11
1.15.0 1.0.x 4.1 4.0, 3.2 3.7 - 3.11
1.14.0 0.990+ 4.1 4.0, 3.2 3.7 - 3.11

Features

Type checking of Model Meta attributes

By inheriting from the TypedModelMeta class, you can ensure you're using correct types for attributes:

from django.db import models
from django_stubs_ext.db.models import TypedModelMeta

class MyModel(models.Model):
    example = models.CharField(max_length=100)

    class Meta(TypedModelMeta):
        ordering = ["example"]
        constraints = [
            models.UniqueConstraint(fields=["example"], name="unique_example"),
        ]

Other typed base classes

  • django_stubs_ext.db.router.TypedDatabaseRouter can be used as base when implementing custom database routers.

Settings

django-stubs has a few settings, which you can list in:

  • pyproject.toml, under the table [tool.django-stubs]
  • mypy.ini under the table [mypy.plugins.django-stubs]

The supported settings are:

  • django_settings_module, a string, default to os.getenv(DJANGO_SETTINGS_MODULE).

    Specify the import path of your settings module, the same as Django’s DJANGO_SETTINGS_MODULE environment variable.

  • strict_settings, a boolean, default true.

    Set to false if using dynamic settings, as described below.

FAQ

Is this an official Django project?

No, it is not. We are independent from Django at the moment. There's a proposal to merge our project into the Django itself. You can show your support by liking the PR.

Is it safe to use this in production?

Yes, it is! This project does not affect your runtime at all. It only affects mypy type checking process.

But, it does not make any sense to use this project without mypy.

mypy crashes when I run it with this plugin installed

The current implementation uses Django's runtime to extract information about models, so it might crash if your installed apps or models.py are broken.

In other words, if your manage.py runserver crashes, mypy will crash too. You can also run mypy with --tb option to get extra information about the error.

I cannot use QuerySet or Manager with type annotations

You can get a TypeError: 'type' object is not subscriptable when you will try to use QuerySet[MyModel], Manager[MyModel] or some other Django-based Generic types.

This happens because these Django classes do not support __class_getitem__ magic method in runtime.

  1. You can go with our django_stubs_ext helper, that patches all the types we use as Generic in django.

    Install it:

    pip install django-stubs-ext  # as a production dependency

    And then place in your top-level settings:

    import django_stubs_ext
    
    django_stubs_ext.monkeypatch()

    You can add extra types to patch with django_stubs_ext.monkeypatch(extra_classes=[YourDesiredType])

  2. You can use strings instead: 'QuerySet[MyModel]' and 'Manager[MyModel]', this way it will work as a type for mypy and as a regular str in runtime.

How can I create a HttpRequest that's guaranteed to have an authenticated user?

Django's built in HttpRequest has the attribute user that resolves to the type

Union[User, AnonymousUser]

where User is the user model specified by the AUTH_USER_MODEL setting.

If you want a HttpRequest that you can type-annotate with where you know that the user is authenticated you can subclass the normal HttpRequest class like so:

from django.http import HttpRequest
from my_user_app.models import MyUser


class AuthenticatedHttpRequest(HttpRequest):
    user: MyUser

And then use AuthenticatedHttpRequest instead of the standard HttpRequest for when you know that the user is authenticated. For example in views using the @login_required decorator.

Why am I getting incompatible return type errors on my custom managers?

If you declare your custom managers without generics and override built-in methods you might see an error message about incompatible error messages, something like this:

from django.db import models

class MyManager(model.Manager):
    def create(self, **kwargs) -> "MyModel":
        pass

will cause this error message:

error: Return type "MyModel" of "create" incompatible with return type "_T" in supertype "BaseManager"

This is happening because the Manager class is generic, but without specifying generics the built-in manager methods are expected to return the generic type of the base manager, which is any model. To fix this issue you should declare your manager with your model as the type variable:

class MyManager(models.Manager["MyModel"]):
    ...

How do I annotate cases where I called QuerySet.annotate?

Django-stubs provides a special type, django_stubs_ext.WithAnnotations[Model, <Annotations>], which indicates that the Model has been annotated, meaning it requires extra attributes on the model instance.

You should provide a TypedDict of these attributes, e.g. WithAnnotations[MyModel, MyTypedDict], to specify which annotated attributes are present.

Currently, the mypy plugin can recognize that specific names were passed to QuerySet.annotate and include them in the type, but does not record the types of these attributes.

The knowledge of the specific annotated fields is not yet used in creating more specific types for QuerySet's values, values_list, or filter methods, however knowledge that the model was annotated is used to create a broader type result type for values/values_list, and to allow filtering on any field.

from typing import TypedDict
from django_stubs_ext import WithAnnotations
from django.db import models
from django.db.models.expressions import Value


class MyModel(models.Model):
    username = models.CharField(max_length=100)


class MyTypedDict(TypedDict):
    foo: str


def func(m: WithAnnotations[MyModel, MyTypedDict]) -> str:
    print(m.bar)  # Error, since field "bar" is not in MyModel or MyTypedDict.
    return m.foo  # OK, since we said field "foo" was allowed


func(MyModel.objects.annotate(foo=Value("")).get(id=1))  # OK
func(MyModel.objects.annotate(bar=Value("")).get(id=1))  # Error

Why am I getting incompatible argument type mentioning _StrPromise?

The lazy translation functions of Django (such as gettext_lazy) return a Promise instead of str. These two types cannot be used interchangeably. The return type of these functions was therefore changed to reflect that.

If you encounter this error in your own code, you can either cast the Promise to str (causing the translation to be evaluated), or use the StrPromise or StrOrPromise types from django-stubs-ext in type hints. Which solution to choose depends depends on the particular case. See working with lazy translation objects in the Django documentation for more information.

If this is reported on Django code, please report an issue or open a pull request to fix the type hints.

How to use a custom library to handle Django settings?

Using something like django-split-settings or django-configurations will make it hard for mypy to infer your settings.

This might also be the case when using something like:

try:
    from .local_settings import *
except Exception:
    pass

So, mypy would not like this code:

from django.conf import settings

settings.CUSTOM_VALUE  # E: 'Settings' object has no attribute 'CUSTOM_VALUE'

To handle this corner case we have a special setting strict_settings (True by default), you can switch it to False to always return Any and not raise any errors if runtime settings module has the given value, for example pyproject.toml:

[tool.django-stubs]
strict_settings = false

or mypy.ini:

[mypy.plugins.django-stubs]
strict_settings = false

And then:

# Works:
reveal_type(settings.EXISTS_AT_RUNTIME)  # N: Any

# Errors:
reveal_type(settings.MISSING)  # E: 'Settings' object has no attribute 'MISSING'

Related projects

To get help

We have Gitter here: https://gitter.im/mypy-django/Lobby If you think you have more generic typing issue, please refer to https://github.com/python/mypy and their Gitter.

Contributing

This project is open source and community driven. As such we encourage contributions big and small. You can contribute by doing any of the following:

  1. Contribute code (e.g. improve stubs, add plugin capabilities, write tests etc) - to do so please follow the contribution guide.
  2. Assist in code reviews and discussions in issues.
  3. Identify bugs and issues and report these
  4. Ask and answer questions on StackOverflow

You can always also reach out in gitter to discuss your contributions!

django-stubs's People

Contributors

adamchainz avatar aleksanb avatar alexerson avatar andersk avatar asottile avatar brianhelba avatar bullfest avatar decentral1se avatar dependabot[bot] avatar flaeppe avatar gabdug avatar github-actions[bot] avatar hannseman avatar intgr avatar kalekseev avatar kszmigiel avatar ljodal avatar mkurnikov avatar mthuurne avatar pig208 avatar pre-commit-ci[bot] avatar q0w avatar rik avatar ryanwalker277 avatar sajaehyukc avatar sobolevn avatar sudosubin avatar syastrov avatar unknownplatypus avatar viicos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-stubs's Issues

Type of fields on non-model classes resolves to return type

Fields on non-model classes are resolving to the return type as if they were on a model. Use case is binding the field with other data in order to access its field name and to_python methods while doing data collection.

from typing import Generic, Text, TypeVar
from django.db import models

A = TypeVar('A')
B = TypeVar('B')

def field_name(field: models.Field[A, B]) -> Text:
    reveal_type(field)  # Revealed type is 'django.db.models.fields.Field[A`-1, B`-2]
    return field.name

class BoundWithField(Generic[A, B]):
    field: models.Field[A, B]
    def field_name(self) -> Text:
        reveal_type(self.field)  # Revealed type is 'B`2
        return self.field.name  # "B" has no attribute "name"

Catch type error on django models

It is possible to have type errors for django models?

class A(models.Model):
    pass

class B(models.Model):
    pass

def service(a: A) -> int:
    pass

a_instance = A()
b_instance = B()
service(b)  # no type error

It would help a lot if this could be caught earlier on the editor.
Because all models inherit from models.Model and

Every class is also a valid type. Any instance of a subclass is also compatible with all superclasses

I' m trying to figure if there is an option to detect this errors.

Generic params are not passed correctly to QuerySet methods' return type

[CASE custom_unannotated_manager_select_related_returns_proper_queryset]
from django.db import models
class MyManager(models.Manager):
    pass
class User(models.Model):
    objects = MyManager()

reveal_type(User.objects)  # E: Revealed type is 'main.MyManager[main.User]'
reveal_type(User.objects.select_related())  # E: Revealed type is 'django.db.models.query.QuerySet[main.User*, main.User*]'
[/CASE]

Type inference fails for foreign keys with custom app names

If you have a foreign key or similar that refers to a model with a string, and you have a custom app name for the app where that model lives, the inferred type falls back to Any:

class UserConfig(AppConfig):
    name = 'hyre.user'
    label = 'hyre__user'

if TYPE_CHECKING:
    from hyre.user.models import User

class MyClass(models.Model):
    some_fk = models.ForeignKey( 'hyre__user.User', ...)

mypy-django will look for the model User in a file called hyre__user, but only hyre.user exists in all_modules in helpers.py.

Type of model is not model's class

First of all, django-stubs is an amazing project. I built some workarounds for typing Django myself but this project is so much more comprehensive and better. So thank you very much for your work!

However, I have run into my first issue:

For the following code

class Comment(models.Model):
    # fields
    pass

class OtherModel(models.Model):
    comments = GenericRelation(Comment)

mypy complains with the following error message:

error: Argument 1 to "GenericRelation" has incompatible type "Type[Comment]"; expected "Union[Type[Model], str]"

Expecting Union[Type[Model], str] is completely correct imho. But since Comment is a subclass of Model everything should be fine.

In order to find the underlying problem I inserted an reveal_type(Comment) call which gave me the following output:

Revealed type is 'def (**kwargs: Any) -> comments.models.Comment'

Maybe this is totally fine and due to the internals of the plugin. But I expected it to be Type[Comment] which could also be the reason why mypy doesn't recognize it as compatible to Type[Model].

(What I don't understand is why mypy says Type[Comment] in the first error message which contradicts the 'revealed type' output)

Use NewTypes for model pks

I was wondering whether there was any plans or desire to use NewTypes for model primary key fields. This would allow for stronger typing when passing model ids around, rather than those ending up as being int (or similar).

This might look like this:

class Thing(models.Model): ...
class Other(models.Model):
    thing = models.ForeignKey(Thing, ...)

thing = Thing.objects.get()
thing_pk: Thing.PK = thing.pk
other = Other.objects.get(thing_id=thing_pk)
assert thing_pk == other.thing_id

# These would all type error because of the mismatches:
Other.objects.get(pk=thing_pk)
Other.objects.get(pk=Thing.PK(4))
Other.objects.get(thing_id=other.pk)
other.thing_id = other.pk

# Maybe this would error too? I'm not sure.
Other.objects.get(pk=4)

(I'm not set at all on the primary key type being a subclass and I appreciate that actually using the type at runtime would require changes to Django too, so this might be something to look at if/after the stubs become part of Django itself?)

I appreciate that not all users might want this as it adds a certain amount of overhead for common patterns, so it might be that we allow the underlying equivalent type (here, int) to be accepted as well, though on the flip side that could mean that you think you've got more safety than you really have. An alternative might be to make this configurable.

My main use-case is where I'm passing around lists of ids both within my Django codebase as well as in communications with other internal services (via JSON). These scenarios operate with ids rather than model instances, but I'd like to still benefit from type checking and documentation.

v0.12.0 seems to have been published with dev code

So as I mentioned in my previous issue I got this package to work by downgrading to 0.12.0, after a few runs it started once in a while crashing with this error message though:

django-stubs bug

After some more debugging I found that there was a function in my distro version that's not in the Github v0.12.0 tag, and that was where the bug was, I also realized that this function that doesn't exist on Github at any time I can find (was looking through the git history of the main.py file) was being called like this (line 350):

Screenshot from 2019-06-18 07-35-07

which not only has a commented out print statement but much more suspiciously has a return statement before all that logic below which is on Github but can't run in my distro. This leads me to believe the publisher was probably debugging before publishing and forgot to do a git checkout or something of the like to clear their code of debug statements before publishing. Not sure if it's possible to overwrite a publish on Pypi, probably not, and I guess this is already fixed in future releases but if there is a way of fixing it that would be cool. For me deleting that return statement seems to make the code work again

Django2.2 support

HI, @mkurnikov! Thanks for building this package.

Are there any plans on [email protected] support? Since it is LTS, it might be a good idea to use this version.

And a general question: what is your idea about different versions support?
Is there any existing discussion about it?

method_decorator should accept list first argument

The following code is valid, but yields a warning I think is incorrect:

from django.utils.decorators import method_decorator
from wherever import decorator_1, decorator_2

new_decorator = method_decorator(
    [
        decorator_1,
        decorator_2,
    ],
    name='dispatch',
)

errors with:

Argument 1 to "method_decorator" has incompatible type "List[Any]"; expected "Union[Callable[..., Any], Set[Callable[..., Any]], Tuple[Callable[..., Any], Callable[..., Any]]]"

I'm guessing the fix is to add List or perhaps Sequence or Container into the allowed container types in the union. (If you agree that's a good solution I'd be happy to put up a PR)

Module 'django.db.models.deletion' has no attribute 'get_candidate_relations_to_delete'

Thanks for these type stubs. I'm just trying them out on a large Django codebase and I've hit a warning which seems incorrect:

from django.db.models.deletion import get_candidate_relations_to_delete

will emit an error about the memcached backend not being present:

Module 'django.db.models.deletion' has no attribute 'get_candidate_relations_to_delete'

(sorry these ended up as three separate issues, in hindisght it might have made more sense to report them in the same go)

Cannot find module named 'rest_framework'

Hi,

Do you have any plans to support Django Rest Framework?

I'm getting the following problem:

from rest_framework import serializers

class MySerializer(serializers.ModelSerializer):
    pass

The mypy --strict output:

main\rest_api\serializers.py:1: error: Cannot find module named 'rest_framework'
main\rest_api\serializers.py:1: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports
main\rest_api\serializers.py:4: error: Class cannot subclass 'ModelSerializer' (has type 'Any')

v0.12.1 broke the mypy_django_plugin

I was just trying to install this package for the first time, but kept getting import errors Error importing plugin 'mypy_django_plugin.main' which seems to be the same error you get if you just write something gibberish, aka it can't find the package. I was super stumped for a while and was debugging a lot, ending up also trying to install another plugin just to see if it was mypy but that worked. I also tried just importing mypy_django_plugin but that would tell me Plugin 'mypy_django_plugin' does not define entry point function "plugin", so I tried importing the plugin function into __init__.py but then the previous error came again.

I then saw that it was a pretty recent release I'd downloaded so I tried downgrading to 0.12.0 and it suddenly worked, so it looks like you somehow broke an import in 0.12.1 ?

I'm on Ubuntu 18.04 using python 3.6.7 if that helps

Trouble with Poetry and mypy plugin

I've been having issues with poetry https://github.com/sdispater/poetry and getting the mypy plugin to work.

Here is my setup:

❯ poetry --version
Poetry 0.11.0

pyproject.toml

[tool.poetry]
name = "tmp.2kfpjvxv"
version = "0.1.0"
description = ""
authors = []

[tool.poetry.dependencies]
python = "*"
django = "^2.1"

[tool.poetry.dev-dependencies]
mypy = "^0.660.0"
django-stubs = "^0.2.0"

mypy.ini

[mypy]
python_version=3.6
show_column_numbers=True
warn_incomplete_stub = True
warn_redundant_casts = True
warn_unused_configs = True
scripts_are_modules = True
incremental = True
ignore_missing_imports = True
check_untyped_defs = True
warn_no_return = True
warn_return_any = True
warn_unused_ignores = True
no_implicit_optional = True
plugins =
    mypy_django_plugin.main

And running mypy gives the following error:

poetry run mypy --config-file mypy.ini src

mypy.ini:15:1: error: Error importing plugin 'mypy_django_plugin.main'

Note: the django stubs works, the only issue is with the plugin

Here are the site-packages in .venv

Django-2.1.5.dist-info/
__pycache__/
_ast27.cpython-36m-darwin.so*
_ast3.cpython-36m-darwin.so*
django/
django-stubs/
django_stubs-0.2.0.dist-info/
easy_install.py
mypy/
mypy-0.660.dist-info/
mypy_django_plugin/
mypy_extensions-0.4.1.dist-info/
mypy_extensions.py
pip/
pip-9.0.3.dist-info/
pkg_resources/
pytz/
pytz-2018.9.dist-info/
setuptools/
setuptools-39.0.1.dist-info/
typed_ast/
typed_ast-1.2.0.dist-info/

Import error

When I try to use the plugin it returns me this error:
mypy.ini:2: error: Error importing plugin 'mypy_django_plugin.main'

mypy.ini:

[mypy]
plugins =
    mypy_django_plugin.main

pip freeze:
django-stubs==0.1.0

Typecheck all test folders in Django test suite

I've set up typechecking of Django test suite via
https://github.com/mkurnikov/django-stubs/blob/master/scripts/typecheck_tests.py
for some of the folders.
Now we need to enable it for all test folders.

To add stubs for test folder:

  1. Choose one from here
    https://github.com/django/django/tree/master/tests

  2. Add it to the TESTS_DIRS constant
    https://github.com/mkurnikov/django-stubs/blob/master/scripts/typecheck_tests.py#L30

  3. Run typecheck_tests.py.

  4. Fix all occurred errors, possibly ignoring ones for the test code itself using IGNORED_ERROR_PATTERNS constant.

FormMixin is incompatible with SuccessMessageMixin

From what I can tell, the Django sources for these two are fine to be mixed together, however the type annotations seem to disagree:

from django.views.generic.edit import FormMixin
from django.contrib.messages.views import SuccessMessageMixin

reveal_type(FormMixin.form_valid)
# Revealed type is 'def (self: ..., form: django.forms.forms.BaseForm) -> django.http.response.HttpResponse'
reveal_type(SuccessMessageMixin.form_valid)
# Revealed type is 'def (self: ..., form: django.forms.forms.Form) -> django.http.response.HttpResponseRedirect'

class FooView(FormMixin, SuccessMessageMixin):
    pass

# Definition of "form_valid" in base class "FormMixin" is incompatible with definition in base class "SuccessMessageMixin"

I suspect that the signature of FormMixin is the one we want to use, so the fix is to update SuccessMessageMixin to match. (If you agree that's a good solution I'd be happy to put up a PR)

CharField with blank=True should not be considered nullable

AFAIK, CharField(blank=True,...) just means that the string can be 0-length, and doesn't mean that it's Optional/nullable. The documentation on blank also seems to suggest this, saying that it "will allow the entry of an empty value", which for a string is just a 0-length string.

I think the offending code is fields.py:105

I can make a pull request to remove (or comment out) that block of code if needed

Support stricter QuerySet row types for values/values_list via plugin magic

I'm gathering a list of things necessary to implement good support for adding specific types for values / values_list based on the current QuerySet + arguments to those methods + model information.

Basic support:

  • Lookup fields passed in on QuerySet's model (probably can reuse a lot of the information already used to support field access on model instances).
  • Support 'id' / 'pk' lookups
  • Support passing no arguments to values / values_list. It returns the correct type (Tuple/NamedTuple/Dict), but without field types specified.
  • Add a flag to mypy_django.ini (called e.g. use_strict_queryset_row_types, default false) to turn on the feature. Document it in the README. I decided not to do this, since the fallbacks (e.g. to Any) should not cause problems.

Related fields support:

  • Lookup fields on models related to QuerySet (when using __), recursively.
  • For a related field called related_field, support both related_field and related_field_id as arguments (they should return the related model's PK type).
  • Support models using inheritance.

Other nice-to-have + difficult/dynamic cases:

  • When no arguments are passed to values / values_list, it should return all fields (extra + annotated + model fields?).
  • Support QuerySet's that had previously been annotate-ed. We could keep track of extra annotated fields on the type metadata. It will sometimes be difficult to determine the correct type for some of those. We could try to rely on type-annotating the output_field attribute or property on the appropriate subclass of Expression in the stubs to get the most specific types. Maybe in some cases the plugin will have to do some magic to figure it out if it's possible (e.g. where F expressions are used).
  • Support annotating without an alias specified (e.g. Book.objects.annotate(Max('id')).values_list('id__max', flat=True)). It seems like it uses the lower-cased name attribute of the Aggregate appended to the field expression in the case there is only one expression.
  • Raise an error when annotating with an alias that conflicts with a model field name.
  • values supports adding additional annotations using keyword arguments. Not difficult once annotations are supported.
  • Support expressions passed to values_list (e.g. Entry.objects.values_list('id', Lower('headline')))). Should be doable once annotations are supported.
  • Support lookups in values/values_list. e.g. the docs gives an example with a custom lookup Blog.objects.values('name__lower'). Probably it's only feasible for the built-in lookups. If we have lookup support, then supporting type-checking .filter and Q objects is not far-fetched.
  • What happens when you use select_related / prefetch_related?

Related, but outside of scope for this task:

  • Adding extra fields to Model instances with the correct types if you call annotate on the QuerySet.

Is there anything missing?

Django `ForeignKey` error: `Invalid value for a to= parameter` with `str` value

Hey folks!

Any idea why I'm getting this error on a ForeignKey to relation with a string value? The to parameter can either be reference to the model class or a string path to resolve the model class (to avoid circular references). If I change this to value from a string to a reference to the model class itself, I no longer get the linter warning.

  $  mypy story
story/models.py:18: error: Invalid value for a to= parameter: 'Author'

This code gives me the warning from mypy:

# story/models.py
class Story(models.Model):
    ...
    author = models.ForeignKey('Author', on_delete=models.CASCADE)

If I change it to this, then there is no warning (Author model is defined in the same file):

# story/models.py
class Story(models.Model):
    ...
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

I checked the stubs for ForeignKey in this codebase and it seems to correctly indicate Union of string and model class, so I'm a little stumped as to why this problem would happen.

get_object_or_404 has type Model instead of Team

get_object_or_404 is returning type Model when I would expect it to return type Team.

Here's the example:

from django.shortcuts import get_object_or_404

from django.db import models

class Team(models.Model):
    name = models.CharField(max_length=255)
    is_public = models.BooleanField(default=False)


team: Team = get_object_or_404(Team, pk=5)
# example.py:12:1: error: Incompatible types in assignment (expression has type "Model", variable has type "Team")
mypy = "^0.670
mypy_extensions = "^0.4.1"
django-stubs = "^0.3.0"

Consider changing the project license to MIT

I would like to propose that the project's license be changed to an MIT license. I have had problems in the past with organising developer efforts to contribute to projects with a 3-clause BSD licence. The third clause prohibiting promotion without consent raises concerns around promoting developer hackathons for working on projects. I'd prefer to be able to promote a hackathon for contributing to free software projects without having to first ask for consent. A 2-clause BSD licence would also be fine.

Thank you!

Slow pip install due to `django-sources`

Hi,

I've tried to run scripts/typecheck_tests.py to verify some changes.
AFAIK is needed to re-install django-stubs in order to re-run scripts/typecheck_tests.py with modifications. However, this scripts install django-sources in project root folder and this affect pip install -U speed:

$ time pip3.7 install -U .
Processing /Users/kote/github/django-stubs
Requirement already satisfied, skipping upgrade: Django in /usr/local/lib/python3.7/site-packages (from django-stubs==0.2.0) (2.1.5)
Requirement already satisfied, skipping upgrade: mypy in /usr/local/lib/python3.7/site-packages (from django-stubs==0.2.0) (0.660)
Requirement already satisfied, skipping upgrade: pytz in /usr/local/lib/python3.7/site-packages (from Django->django-stubs==0.2.0) (2018.9)
Requirement already satisfied, skipping upgrade: typed-ast<1.3.0,>=1.2.0 in /usr/local/lib/python3.7/site-packages (from mypy->django-stubs==0.2.0) (1.2.0)
Requirement already satisfied, skipping upgrade: mypy-extensions<0.5.0,>=0.4.0 in /usr/local/lib/python3.7/site-packages (from mypy->django-stubs==0.2.0) (0.4.1)
Building wheels for collected packages: django-stubs
  Running setup.py bdist_wheel for django-stubs ... done
  Stored in directory: /Users/kote/Library/Caches/pip/wheels/d7/e7/6b/7e469272d213a3673cde0b8793a8d739ad8407a3676a70dabf
Successfully built django-stubs
Installing collected packages: django-stubs
  Found existing installation: django-stubs 0.2.0
    Uninstalling django-stubs-0.2.0:
      Successfully uninstalled django-stubs-0.2.0
Successfully installed django-stubs-0.2.0

real	1m10.033s
user	0m13.555s

# without django-sources
$ time pip3.7 install -U .
Processing /Users/kote/github/django-stubs
Requirement already satisfied, skipping upgrade: Django in /usr/local/lib/python3.7/site-packages (from django-stubs==0.2.0) (2.1.5)
Requirement already satisfied, skipping upgrade: mypy in /usr/local/lib/python3.7/site-packages (from django-stubs==0.2.0) (0.660)
Requirement already satisfied, skipping upgrade: pytz in /usr/local/lib/python3.7/site-packages (from Django->django-stubs==0.2.0) (2018.9)
Requirement already satisfied, skipping upgrade: mypy-extensions<0.5.0,>=0.4.0 in /usr/local/lib/python3.7/site-packages (from mypy->django-stubs==0.2.0) (0.4.1)
Requirement already satisfied, skipping upgrade: typed-ast<1.3.0,>=1.2.0 in /usr/local/lib/python3.7/site-packages (from mypy->django-stubs==0.2.0) (1.2.0)
Building wheels for collected packages: django-stubs
  Running setup.py bdist_wheel for django-stubs ... done
  Stored in directory: /Users/kote/Library/Caches/pip/wheels/d7/e7/6b/7e469272d213a3673cde0b8793a8d739ad8407a3676a70dabf
Successfully built django-stubs
Installing collected packages: django-stubs
  Found existing installation: django-stubs 0.2.0
    Uninstalling django-stubs-0.2.0:
      Successfully uninstalled django-stubs-0.2.0
Successfully installed django-stubs-0.2.0

real	0m2.939s
user	0m1.677s
sys	0m1.193s

Improve fields annotations

Hi,

I've tried checking my project and got lots of field-related warnings, most about extra parameters, duplicate parameters, etc.
I've narrowed issue down to Field signature and it's inherited classes.
Current signature is:
def __init__(self, **kwargs: Any): ...
And as example CharField:
def __init__(self, max_length: int = ..., **kwargs: Any): ...

Real Field signature has to accept all arguments as positional, and to do it's inherited classes. It might be not practical to supply more than 1-2 arguments as positional, but it's possible:

def __init__(
    self,
    verbose_name: str = ...,
    name: str = ...,
    primary_key: bool = ...,
    max_length: int = ...,
    unique: bool = ...,
    blank: bool = ...,
    null: bool = ...,
    db_index: bool = ...,
    rel: Any = ..., ## ???
    default: Any = ..., ## ???
    editable: bool = ...,
    serialize: bool = ...,
    unique_for_date: bool = ...,
    unique_for_month: bool = ...,
    unique_for_year: bool = ...,
    choices: Any = ..., # ???
    help_text: str = ...,
    db_column: Any = ..., # ???
    db_tablespace: Any = ..., # ???
    auto_created: bool = ...,
    validators: Any = ..., #???
) -> None: ...

So CharField's max_length is just one of Field parameters.

Please advise - should it be fixed directly, or is it an issue in automated code annotator ?
If it should be fixed manually - should all inherited fields duplicate Field signature and add new params, or will (new_param: Type, **kwargs) work fine ? I'm not sure if mypy will check Field signature in this case.

Incorrect Manager type for child model's objects when parent has circular imports

After running on an internal codebase, where we have a few places using inherited models, I encountered some issues in figuring out the correct Manager type for an inherited Model (which otherwise works great!), when there is an import cycle.

I created a relatively small testcase that demonstrates the problem:

[CASE managers_multiple_inheritance_multiple_files_import_cycle]
from django.db import models
from myapp.models import Child
reveal_type(Child.objects) # E: Revealed type is 'django.db.models.manager.Manager[myapp.models.child.Child]'
Child.objects.create(c=True, p="abc", other_id=123)

[file myapp/__init__.py]
[file myapp/models/__init__.py]
from .other import Other
from .parent import Parent
from .child import Child

[file myapp/models/other.py]
from django.db import models
class Other(models.Model):
    o = models.CharField(max_length=255)

[file myapp/models/parent.py]
from django.db import models
from myapp.models import Other
# Changing the above line to the following fixes around the problem:
#from myapp.models.other import Other
class Parent(models.Model):
    p = models.CharField(max_length=255)
    other = models.ForeignKey(Other, on_delete=models.CASCADE)

[file myapp/models/child.py]
from django.db import models
from myapp.models import Parent
class Child(Parent):
    c = models.BooleanField(default=True)

reveal_type(Child.objects) gives: Revealed type is 'django.db.models.manager.Manager[myapp.models.parent.Parent]'
But it should be django.db.models.manager.Manager[myapp.models.child.Child].

If I change the line from myapp.models import Other to from myapp.models.other import Other in myapp/models/parent.py, then it behaves as expected, so there is a fairly easy workaround.

I don't know if this is something to do with mypy itself or how this plugin works.

Django.db.models.functions missing almost all re-imports

Initial error: "error: Module 'django.db.models.functions' has no attribute 'Coalesce'" has only: from django.db.models.functions has only one line: from .text import Lower as Lower`, while django has:

from .comparison import Cast, Coalesce, Greatest, Least, NullIf
from .datetime import (
    Extract, ExtractDay, ExtractHour, ExtractIsoYear, ExtractMinute,
    ExtractMonth, ExtractQuarter, ExtractSecond, ExtractWeek, ExtractWeekDay,
    ExtractYear, Now, Trunc, TruncDate, TruncDay, TruncHour, TruncMinute,
    TruncMonth, TruncQuarter, TruncSecond, TruncTime, TruncWeek, TruncYear,
)
from .math import (
    Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Cot, Degrees, Exp, Floor, Ln, Log,
    Mod, Pi, Power, Radians, Round, Sin, Sqrt, Tan,
)
from .text import (
    Chr, Concat, ConcatPair, Left, Length, Lower, LPad, LTrim, Ord, Repeat,
    Replace, Reverse, Right, RPad, RTrim, StrIndex, Substr, Trim, Upper,
)
from .window import (
    CumeDist, DenseRank, FirstValue, Lag, LastValue, Lead, NthValue, Ntile,
    PercentRank, Rank, RowNumber,
)

warning Field is not callable

Hello guys,
I get multiple warnings while determine field in Model class, such as EmailField, BooleanField, PositiveSmallIntegerField, PositiveIntegerField, DateTimeField, TextField, NullBooleanField, UUIDField, URLField
The warning everywhere the same:
This inspection highlights attempts to call objects which are not callable, like, for example, tuples.

Model Field in type annotation runtime error

Originally posted on the gitter:

I'm coming across this issue where I'm trying to use a Field in a type annotation something like: Dict[Field, Any]

If i use mypy on this with django-stubs enabled, i get this error message:

`Missing type parameters for generic type`

so then i change it to Dict[Field[Any, Any], Any], and that fixes the problem in mypy, but at runtime, it fails:

`TypeError: 'type' object is not subscriptable`

Module 'django.core.cache.backends' has no attribute 'memcached'

Thanks for these type stubs. I'm just trying them out on a large Django codebase and I've hit a warning which seems incorrect:

from django.core.cache.backends import dummy, memcached

will emit an error about the memcached backend not being present:

Module 'django.core.cache.backends' has no attribute 'memcached'

"Type[Model]" has no attribute "objects"

Not sure what to do, having to type: ignore the second line below:

User = django.contrib.auth.get_user_model()
user = User.objects.create_user(email=data.get("email"), signup_nonce=signup_nonce)

KeyError: 'django.conf.global_settings'

Not sure where to report this, or even how to debug it, but I've been receiving the following error for the past few days that seems to be coming from django-stubs:

$ c&&DJANGO_PROJECT_SETTINGS=project.settings mypy --pdb --show-traceback project/app1/folder/folder2/somefile.py
~/env/lib/python3.7/site-packages/django-stubs/conf/__init__.pyi:10: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.670
Traceback (most recent call last):
  File "~/env/bin/mypy", line 10, in <module>
    sys.exit(console_entry())
  File "mypy/semanal.py", line 3787, in accept
  File "mypy/nodes.py", line 845, in accept__Node_glue
  File "mypy/nodes.py", line 846, in accept
  File "mypy/semanal.py", line 801, in visit_class_def__StatementVisitor_glue
  File "mypy/semanal.py", line 804, in visit_class_def
  File "mypy/semanal.py", line 822, in analyze_class
  File "mypy/semanal.py", line 830, in analyze_class_body_common
  File "mypy/semanal.py", line 906, in apply_class_plugin_hooks
  File "~/env/lib/python3.7/site-packages/mypy_django_plugin/transformers/settings.py", line 91, in __call__
    module = api.modules[module_name]
KeyError: 'django.conf.global_settings'
~/env/lib/python3.7/site-packages/django-stubs/conf/__init__.pyi:10: : note: use --pdb to drop into pdb
(Pdb) p api.modules.keys()
dict_keys(['project.app1.folder.folder2.somefile', 'project', 'django.db.models.query', 'django.core.checks', 'django.apps', 'django.core.checks.registry', 'django.test', 'django.contrib.auth', 'django.test.testcases', 'django.test.utils', 'django.contrib.auth.backends', 'django.db.models.options', 'django.contrib.auth.signals', 'django.core.servers.basehttp', 'django.test.runner', 'django.conf', 'django.contrib.postgres.fields', '_ast', '_importlib_modulespec', 'ast', 'types', 'abc', 'typing', 'mmap', 'codecs', 'os.path', 'importlib.abc', 'collections', 'io', 'collections.abc', 'sys', 'posix', 'os', 'importlib.machinery', 'importlib.util', 'importlib', 'builtins', 'email.errors', 'email.charset', 'wsgiref.headers', 'django.core.management.color', 'wsgiref.types', 'django.contrib.postgres.fields.mixins', 'django.contrib.postgres', 'argparse', 'wsgiref', 'django.core.servers', 'contextlib', 'warnings', 'django.contrib.contenttypes', 'django.core.handlers', 'json.encoder', 'json.decoder', '_markupbase', 'html', 'django.urls.utils', 'django.contrib', 'django.contrib.sessions', 'django.contrib.sessions.backends', 'django.http.cookie', 'django.db.migrations.operations.base', 'functools', 'django.db.backends.base', 'django.db.backends', 'django.db.backends.sqlite3', 'threading', 'string', 'django.template.loaders', 'enum', 'django.db.backends.ddl_references', 'django.template.backends', 'tempfile', 'django.core.checks.messages', 'numbers', 'django.db.utils', 'django.core.files.utils', 'time', 'itertools', 'uuid', 'unittest.mock', 'django.utils.safestring', 'django.core', 'django.utils', 'django.utils.version', 'mypy_extensions', 'typing_extensions', '__future__', 'project.office', 'project.office.bankimport', 'project.office.bankimport.ml', 'email.header', 'http', 'wsgiref.util', 'socket', 'json', 'django.urls.converters', 'html.parser', 'logging', 're', 'django.core.files.temp', 'django.utils.datastructures', 'decimal', 'django.core.files.base', 'datetime', 'django', 'email.contentmanager', 'email.policy', 'email.message', 'wsgiref.handlers', 'socketserver', 'django.urls.resolvers', 'django.db.backends.utils', 'sqlite3.dbapi2', 'unittest', 'django.core.files', 'django.forms.utils', 'django.core.exceptions', 'email', 'django.urls.conf', 'django.urls.base', 'sqlite3', 'django.core.files.images', 'django.core.validators', 'django.core.files.uploadedfile', 'http.server', 'django.contrib.auth.validators', 'wsgiref.simple_server', 'django.contrib.auth.base_user', 'django.db.models.fields.proxy', 'django.db', 'django.db.models.deletion', 'django.core.management.base', 'django.core.serializers.base', 'django.core.serializers.python', 'django.contrib.contenttypes.models', 'django.core.serializers.json', 'django.core.handlers.base', 'django.contrib.auth.models', 'django.test.client', 'django.core.handlers.wsgi', 'django.urls.exceptions', 'django.http.response', 'django.template.smartif', 'django.urls', 'django.contrib.sessions.backends.base', 'django.http', 'django.apps.config', 'django.db.backends.base.base', 'django.template.loader_tags', 'django.template.defaulttags', 'django.http.request', 'django.db.models.sql.subqueries', 'django.utils.functional', 'django.db.backends.base.schema', 'django.db.backends.sqlite3.base', 'django.db.models.fields.reverse_related', 'django.db.models.fields.related_descriptors', 'django.template.exceptions', 'django.template.context', 'django.template.utils', 'django.template.loaders.base', 'django.template.library', 'django.template.base', 'django.db.models.sql.datastructures', 'django.db.models.sql', 'django.core.files.storage', 'django.db.models.sql.where', 'django.db.models.sql.compiler', 'django.db.models.fields.mixins', 'django.db.models.indexes', 'django.db.models.lookups', 'django.db.models.fields.related', 'django.db.models.fields', 'django.db.models.aggregates', 'django.template', 'django.template.engine', 'django.template.backends.base', 'django.db.models.sql.query', 'django.db.models.expressions', 'django.db.models.fields.files', 'django.forms.formsets', 'django.db.models.query_utils', 'django.db.models.manager', 'django.db.models.base', 'django.db.models', 'django.forms.renderers', 'django.forms.boundfield', 'django.forms.fields', 'django.forms.widgets', 'django.forms.models', 'django.forms.forms', 'django.forms', 'django.core.files.uploadhandler', 'django.dispatch.dispatcher', 'django.db.migrations.operations.models', 'django.db.migrations.operations.fields', 'django.utils.html', 'django.db.migrations.state', 'django.apps.registry', 'django.db.models.fields.related_lookups', 'django.utils.tree', 'django.db.migrations.operations.special', 'django.dispatch', 'django.db.migrations.migration', 'django.template.defaultfilters', 'django.db.migrations.operations', 'django.db.models.signals', 'django.db.migrations', 'django.core.serializers', 'django.core.wsgi', 'django.contrib.postgres.fields.citext', 'django.contrib.postgres.fields.array', 'django.contrib.contenttypes.fields'])
(Pdb) p self.settings_modules
['django.conf.global_settings']

Unfortunately, our codebase is too big to reduce to a test case, but I can do local debugging if you let me know what/where to look.

Module 'django.db.backends.postgresql' has no attribute 'base'

Thanks for these type stubs. I'm just trying them out on a large Django codebase and I've hit a warning which seems incorrect:

from django.db.backends.postgresql import base

will emit an error about the base module not being present:

Module 'django.db.backends.postgresql' has no attribute 'base'

Python 3.6: ModuleNotFoundError: No module named 'dataclasses'

Your fix mkurnikov@dcb4da3 is actually not working, because it seems that the .whl file was built using Python 3.7 and the dataclasses dependency was not added to the wheel.

$ virtualenv --python /usr/bin/python3.6 py36
$ . py36/bin/activate
(py36) $ pip install django-stubs
Collecting django-stubs
  Using cached https://files.pythonhosted.org/packages/4e/16/03c7804694c16e5f6c159ef527ba6cbdaf2c1cfc76edc2c0f1daeead798d/django_stubs-0.12.1-py3-none-any.whl
Successfully installed django-stubs-0.12.1 mypy-0.701 mypy-extensions-0.4.1 typed-ast-1.3.5 typing-extensions-3.7.2

(py36) $ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypy_django_plugin
>>> from mypy_django_plugin import main
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "py36/lib/python3.6/site-packages/mypy_django_plugin/main.py", line 13, in <module>
    from mypy_django_plugin.config import Config
  File "py36/lib/python3.6/site-packages/mypy_django_plugin/config.py", line 4, in <module>
    from dataclasses import dataclass
ModuleNotFoundError: No module named 'dataclasses'

TypeError when using QuerySet generic

This is probably a silly question. I'm getting runtime errors when using the QuerySet[] generic.

Consider this file:

mypy_test.py

from django.contrib.auth.models import User, Permission
from django.db.models.query import QuerySet


def f(queryset: QuerySet[User]) -> QuerySet[User]:
    return queryset.order_by('id')


def g() -> None:
    print(f(User.objects.all()))
    print(f(Permission.objects.all()))

Mypy is working as expected (which tells me, I've configured django-stubs correctly):

mypy src/mypy_test.py
src/mypy_test.py:11: error: Argument 1 to "f" has incompatible type "QuerySet[Permission, Permission]"; expected "QuerySet[User, User]"
exit 1

Only, I can't import this file:

In [1]: import mypy_test
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-040518e7b0e9> in <module>
----> 1 import mypy_test

~/Projects/flatfox-website/src/mypy_test.py in <module>
      3
      4
----> 5 def f(queryset: QuerySet[User]) -> QuerySet[User]:
      6     return queryset.order_by('id')
      7

TypeError: 'type' object is not subscriptable

In [2]:

Why is the interpreter even trying to make sense of the type annotations? I'm confused, appreciating any help!

Oh, and many thanks for your work on this package!

mypy.ini

# Global options:

[mypy]
python_version = 3.6
warn_return_any = True
warn_unused_configs = True
ignore_missing_imports = True
plugins =
    mypy_django_plugin.main

I don't have a mypy_django.ini.

Add support for `_default_manager`

Check whether any Manager instance is defined on the model.
If not, add the default objects attribute.

Also, plugin has to check whether default_manager_name is set in the Meta and set _default_manager to that, and if not, then set it to the first encountered one.

error: "HttpRequest" has no attribute "user"

Hi there,

I have the following code:

class MyView(RedirectView):
    def get_redirect_url(self, *args: Any, **kwargs: Any) -> Optional(str):
        if self.request.user.is_authenticated():
            do_something_with_user()

Which results in:

$ mypy
> api/users/authentication/views.py:28: error: "HttpRequest" has no attribute "user"

Which is probably because the HttpRequest class doesn't really have the user but it is almost always added through the authentication middleware (either User or AnonymousUser).

So how do I fix this?

"Type[Model]" has no attribute "objects" (again?)

Hello. I tried to use your package yesterday and I like it, although I've encountered one issue, when the django model I was accessing had no attribute 'objects', according to mypy. So it's like #16:

...
anchor/users/forms.py:26: error: "Type[Model]" has no attribute "objects"
anchor/users/views.py:38: error: "Type[Model]" has no attribute "objects"
...

The repo where I found that is https://github.com/kam1sh/anchor.

Also, I looked at django-stubs source code, and the class had no 'objects' field at all. Is it intended?

https://github.com/mkurnikov/django-stubs/blob/0e60b70ae4f521e3a527997d6b79e461d9245dfa/django-stubs/db/models/base.pyi#L9-L16

Foreign key reverse relationship: proper types for `<relatedmodel>_set` attributes

Right now a model instance's <relatedmodel>_set attribute has a type of object, when the type should actually be django.db.models.manager.Manager[RelatedModel].

For example, Organization.objects.first().user_set.all() has a type error. Organization.objects.first() has the correct type of Organization, but if there is a User model with an FK to Organization, Organization.objects.first().user_set has a type of object instead of django.db.models.manager.Manager[Organization].

Is there any way to get the <relatedmodel>_set attribute to resolve to the proper type short of casting it each time?

Using django-stubs==0.12.1, Django 2.1.7, Python 3.7.

Missing decorator stubs

I'm seeing a lot of missing stubs errors for Django view decorators:

podcasts/views.py:12: error: No library stub file for module 'django.views.decorators.cache'
podcasts/views.py:13: error: No library stub file for module 'django.views.decorators.csrf'
podcasts/views.py:14: error: No library stub file for module 'django.views.decorators.gzip'
podcasts/views.py:15: error: No library stub file for module 'django.views.decorators.http'

I see the decorators in the django-stubs repo, and I'm running 0.8.0. Any idea why this might be happening?

Assertion errors when working with existing codebase

I'm having one more problem. Background: I'm adding typing to 2y+ codebase, written in django. I started with those mypy settings:

[mypy]
follow_imports=silent
ignore_missing_imports=true
disallow_untyped_defs=true
plugins=mypy_django_plugin.main

# don't show any errors from migrations
[mypy-*.migrations.*]
ignore_errors = true

I'm running mypy with a set of files and modules which are considered to be properly typed, not all files. The problem is that I often run into this problem:

sms/twilio/api.py:11: error: Function is missing a return type annotation
sms/twilio/api.py:29: error: Function is missing a type annotation
sms/twilio/api.py:34: error: Function is missing a type annotation
sms/twilio/api.py:38: error: Function is missing a type annotation
sms/twilio/api.py:56: error: Function is missing a type annotation
sms/tasks/sms.py:16: error: Function is missing a type annotation
Traceback (most recent call last):
  File "/Users/rafal/Projects/censored/venv/bin/mypy", line 11, in <module>
    sys.exit(console_entry())
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/main.py", line 91, in main
    res = build.build(sources, options, None, flush_errors, fscache)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 162, in build
    result = _build(sources, options, alt_lib_path, flush_errors, fscache)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 217, in _build
    graph = dispatch(sources, manager)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 2360, in dispatch
    process_graph(graph, manager)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 2653, in process_graph
    process_fresh_modules(graph, prev_scc, manager)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 2731, in process_fresh_modules
    graph[id].fix_cross_refs()
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/build.py", line 1714, in fix_cross_refs
    self.options.use_fine_grained_cache)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 25, in fixup_module
    node_fixer.visit_symbol_table(tree.names)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 88, in visit_symbol_table
    self.visit_type_info(value.node)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 45, in visit_type_info
    self.visit_symbol_table(info.names)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 90, in visit_symbol_table
    value.node.accept(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/nodes.py", line 782, in accept
    return visitor.visit_var(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 133, in visit_var
    v.type.accept(self.type_fixer)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/types.py", line 620, in accept
    return visitor.visit_instance(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 157, in visit_instance
    a.accept(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/types.py", line 1601, in accept
    return visitor.visit_union_type(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 229, in visit_union_type
    it.accept(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/types.py", line 620, in accept
    return visitor.visit_instance(self)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 150, in visit_instance
    inst.type = lookup_qualified_typeinfo(self.modules, type_ref, self.quick_and_dirty)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 240, in lookup_qualified_typeinfo
    node = lookup_qualified(modules, name, quick_and_dirty)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 254, in lookup_qualified
    stnode = lookup_qualified_stnode(modules, name, quick_and_dirty)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/fixup.py", line 263, in lookup_qualified_stnode
    return lookup_fully_qualified(name, modules, raise_on_missing=not quick_and_dirty)
  File "/Users/rafal/Projects/censored/venv/lib/python3.6/site-packages/mypy/lookup.py", line 47, in lookup_fully_qualified
    assert key in names, "Cannot find %s for %s" % (key, name)
AssertionError: Cannot find models for general.models.CensoredUser

This seems to be happening because of mypy cache. Running rm -rf .mypy_cache always fixes this, but just for the next run.

It usually happens for user model or other "popular" model in the app.

$ python --version
Python 3.6.8
$ mypy --version
mypy 0.670
$ pip freeze | grep django-stubs
django-stubs==0.11.1

it works fine when I remove mypy django plugin.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.