This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eric.smith
Recipients Ricyteach, eric.smith, lukasz.langa, ned.deily
Date 2018-05-11.11:04:53
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1526036693.4.0.682650639539.issue33453@psf.upfronthosting.co.za>
In-reply-to
Content
The more I think about this, the more I think Łukasz is correct that just checking for strings starting with "ClassVar", "typing.ClassVar", or "t.ClassVar" is the correct thing to do. This is the change he made in https://github.com/python-attrs/attrs/pull/367.

In some private email I had discussed extracting the module name, if any, from the string annotation, and looking it up in sys.modules. This doesn't buy you much because you have to know how the caller imported typing. If they used "import typing as t", then you can't look up "t" in sys.modules. You could do some horrible frame trick to find out what the caller knew as "t", but that still won't work in plenty of cases. I don't want to use a complex solution that still doesn't work in all cases, and would indeed work in fewer places than just examining the string. The only name we could reliably detect is "typing.ClassVar", all others wouldn't be in sys.modules correctly.

So, that leaves us with just looking at the string and guessing what the caller meant. I think the three strings that Łukasz suggested are good enough.

This will need to be well documented. The documentation should note that things like this will break:

from __future__ import annotations
from typing import ClassVar as CV
@dataclass
class C:
    x: CV

x will not be a class variable here, since @dataclass will see the annotation as "CV" and not know that it means typing.ClassVar.

InitVar has a similar problem. What strings to use there? "InitVar" and "dataclasses.InitVar", of course. But maybe "dc.InitVar"? It's hard to say with no in-the-field usage examples to search for. I'll start with just the first two strings.

I really don't want to use regexes here. But a refinement would be to not just use .startswith, and instead use a word boundary. After all, "ClassVarOfMine" should probably not be considered a ClassVar. I'll leave that issue for another day, though.

I'll have a patch ready before the sprints are over.
History
Date User Action Args
2018-05-11 11:04:53eric.smithsetrecipients: + eric.smith, ned.deily, lukasz.langa, Ricyteach
2018-05-11 11:04:53eric.smithsetmessageid: <1526036693.4.0.682650639539.issue33453@psf.upfronthosting.co.za>
2018-05-11 11:04:53eric.smithlinkissue33453 messages
2018-05-11 11:04:53eric.smithcreate