Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
higherorderfunctor opened this issue Apr 3, 2019 · 2 comments · Fixed by #109
Closed

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

higherorderfunctor opened this issue Apr 3, 2019 · 2 comments · Fixed by #109

Comments

@higherorderfunctor
Copy link

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"
@syastrov
Copy link
Contributor

At the moment, the stubs represent the most common scenario of fields being instantiated and assigned to attributes inside of model classes.
To make that work, Field in the stubs implements the descriptor protocol (e.g. has a __get__ method).

It's not exactly the truth of how it works in Django (after some poking through the code). Field in Django itself isn't a descriptor.
When a model is instantiated, Django's ModelBase metaclass actually adds the field to the class wrapped in a django.db.models.query_utils.DeferredAttribute, which is a descriptor.

We could choose to represent this in the stubs, and make them "less-usable" in the model field definition scenario if the stubs are used without the mypy django plugin (e.g. with another type-checker). In that case, the mypy django plugin could handle the job of wrapping the attribute in the descriptor on the model when it is defined.

See also python/typing#399

@mkurnikov
Copy link
Member

I've fixed it in ad44a40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants