Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30612 closed Bug (invalid)

cached_property breaks type checking

Reported by: dms-cat Owned by: nobody
Component: Utilities Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

To reproduce:

  1. Use a strict mypy configuration:
    [mypy]
    check_untyped_defs = true
    disallow_untyped_defs = true
    ignore_missing_imports = true
    no_implicit_optional = true
    warn_redundant_casts = true
    warn_return_any = true
    warn_unused_ignores = true
    
  2. Create a model method which returns an optional instance:
    @property
    def area(self) -> Optional[Area]:
    
  3. Try to use this elsewhere as though it's not optional: instance.area.code
  4. Verify that mypy catches this issue:
    error: Item "None" of "Optional[Area]" has no attribute "code"
    
  5. Change the @property annotation to @cached_property.

What happens:

mypy stops complaining about the broken typing.

What should happen:

mypy should still complain like above.

Change History (3)

comment:1 by Mariusz Felisiak, 5 years ago

Component: UncategorizedUtilities
Resolution: needsinfo
Status: newclosed
Type: UncategorizedBug
Version: 2.2master

Please provide a minimal sample project to reproduce this issue, currently it is hard for me to decide where is an issue (if any). Remember about minimal mypy configuration, most of provided custom configuration is probably unnecessary.

in reply to:  1 comment:2 by dms-cat, 5 years ago

Replying to felixxm:

Please provide a minimal sample project to reproduce this issue, currently it is hard for me to decide where is an issue (if any).

To reproduce (not showing stdout/stderr):

$ cd "$(mktemp --directory)"
$ python -m venv virtualenv
$ . virtualenv/bin/activate
$ pip install Django==2.2.2 mypy==0.701
$ django-admin startproject mysite
$ cat > setup.cfg <<EOF
> [mypy]
> check_untyped_defs = true
> disallow_untyped_defs = true
> ignore_missing_imports = true
> no_implicit_optional = true
> warn_redundant_casts = true
> warn_return_any = true
> warn_unused_ignores = true
> EOF
cat > mysite/mysite/models.py <<EOF
from typing import Optional

from django.db import models
from django.utils import cached_property


class Area(models.Model):
    pass


class Site(models.Model):
    area = models.ForeignKey(Area, on_delete=models.CASCADE)

    @cached_property
    def the_area(self) -> Optional[Area]:
        area: Area = self.area
        return area


area = Area.objects.create()
site = Site(area)
print(site.the_area.code)
EOF
$ mypy mysite/mysite/models.py

The last command reports nothing. If you change @cached_property to @property it correctly reports 'mysite/mysite/models.py:22: error: Item "None" of "Optional[Area]" has no attribute "code"'

Remember about minimal mypy configuration, most of provided custom configuration is probably unnecessary.

This isn't provided configuration, we arrived at this configuration in the project as the level of validation we're comfortable with.

comment:3 by Mariusz Felisiak, 5 years ago

Resolution: needsinfoinvalid

Thanks for info. Custom mypy configuration is not necessary to reproduce this issue, it behaves the same without setup.cfg.

I was able to reproduce this behavior, however I don't think that it is a bug in Django. We can consider to re-open this ticket if you will be able to confirm that it is an issue in Django e.g. by providing a patch.

Note: See TracTickets for help on using tickets.
Back to Top