[Django] #30612: cached_property breaks type checking

23 views
Skip to first unread message

Django

unread,
Jul 3, 2019, 5:44:18 PM7/3/19
to django-...@googlegroups.com
#30612: cached_property breaks type checking
-----------------------------------------+------------------------
Reporter: dms-cat | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 2.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
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
}}}
1. Create a model method which returns an optional instance:
{{{
@property
def area(self) -> Optional[Area]:
}}}
1. Try to use this elsewhere as though it's not optional:
`instance.area.code`
1. Verify that `mypy` catches this issue:
{{{
error: Item "None" of "Optional[Area]" has no attribute "code"
}}}
1. 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.

--
Ticket URL: <https://code.djangoproject.com/ticket/30612>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 4, 2019, 1:43:37 AM7/4/19
to django-...@googlegroups.com
#30612: cached_property breaks type checking
---------------------------+--------------------------------------
Reporter: dms-cat | Owner: nobody
Type: Bug | Status: closed
Component: Utilities | Version: master
Severity: Normal | Resolution: needsinfo

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------
Changes (by felixxm):

* status: new => closed
* resolution: => needsinfo
* version: 2.2 => master
* component: Uncategorized => Utilities
* type: Uncategorized => Bug


Comment:

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.

--
Ticket URL: <https://code.djangoproject.com/ticket/30612#comment:1>

Django

unread,
Jul 4, 2019, 5:33:56 PM7/4/19
to django-...@googlegroups.com
#30612: cached_property breaks type checking
---------------------------+--------------------------------------
Reporter: dms-cat | Owner: nobody

Type: Bug | Status: closed
Component: Utilities | Version: master
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------

Comment (by dms-cat):

Replying to [comment:1 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.

--
Ticket URL: <https://code.djangoproject.com/ticket/30612#comment:2>

Django

unread,
Jul 5, 2019, 2:14:09 AM7/5/19
to django-...@googlegroups.com
#30612: cached_property breaks type checking
---------------------------+--------------------------------------
Reporter: dms-cat | Owner: nobody

Type: Bug | Status: closed
Component: Utilities | Version: master
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------+--------------------------------------
Changes (by felixxm):

* resolution: needsinfo => invalid


Comment:

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.

--
Ticket URL: <https://code.djangoproject.com/ticket/30612#comment:3>

Reply all
Reply to author
Forward
0 new messages