python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.28k stars 2.79k forks source link

Runtime use of type_check_only classes should give an error #9531

Open henribru opened 4 years ago

henribru commented 4 years ago

Feature Currently Mypy doesn't seem to care whether a class is marked with type_check_only in a stub file. My proposal is that any runtime use of such a class should produce an error, including importing it outside of if TYPE_CHECKING and using it in annotations without quotes or from __future__ import annotations.

Pitch To create stubs for libraries that define classes dynamically, it's pretty much required to create classes in stubs that don't exist at runtime. Marking these with type_check_only lets you show that these classes can't be used at runtime, but consumers of your stubs could easily still do so accidentally. It would be useful if Mypy could warn them in those cases.

gvanrossum commented 4 years ago

Can you provide an example? Do you have a specific package in mind?

henribru commented 4 years ago

Sure. The specific package that prompted me to suggest this is https://github.com/googleapis/google-api-python-client, which I've been working on generating a stub package for. There are two different aspects of this library where this would be useful:

Dynamically generated classes

All API resources represented by this library are instances of the Resource class that have had methods dynamically created and attached at runtime based on an API schema. To be able to annotate this I generate "fake" subclasses of Resource in the stub files, one for each of the possible dynamically created Resource instances. If the users of my stubs accidentally use one of these subclasses from my stubs in a runtime-context (which could be as simple as forgetting to quote their annotations), their code won't work. It would be useful if Mypy could warn them about this. I was actually a bit surprised when it didn't, because my understanding was type_check_only is precisely for the case where a stub defines somethings that doesn't exist at runtime.

You can see some examples of the classes I've had to generate here: https://github.com/henribru/google-api-python-client-stubs/blob/master/googleapiclient-stubs/_apis/sheets/v4/resources.pyi There's tons of other files like that, but at runtime there's only Resource.

Another case I know of where this is relevant is https://github.com/boto/boto3. It doesn't stick everything onto instances of a single class, but dynamically creates subclasses, which leads to the same kinds of annotations. This stub package looks like it has the same issue as mine of having to include stub-only classes. I'm sure there are many other examples too, but it might be especially prevalent in these kinds of API wrappers.

Object-like dicts

This is probably the more common case. Lots and lots of libraries use dicts as a sort of quasi-object for argument and return types. When creating stubs for these it's really helpful to include TypedDict subclasses for those uses, but again, these won't be available at runtime when they're only present in stub files and it would be nice if Mypy warned you about this.

You can see examples here of this case: https://github.com/henribru/google-api-python-client-stubs/blob/master/googleapiclient-stubs/_apis/sheets/v4/schemas.pyi. These are only available in the stub package, so users of the stubs need to take care about where they use them.

gvanrossum commented 4 years ago

Yeah, that's not an unreasonable feature request. Are you interested in implementing this for mypy?

henribru commented 4 years ago

I think that would depend on how challenging it is. Do you have some insight into what it would take to implement?

gvanrossum commented 4 years ago

I think that would depend on how challenging it is. Do you have some insight into what it would take to implement?

Alas, I don't have time to look into that. I suggest that you try for about an hour and then report what you've learned.

KotlinIsland commented 2 years ago

Mypy should inform users that type_check_only isn't supported at all. It's not documented anywhere that support isn't provided.

AlexWaygood commented 2 years ago

Closing this issue as a duplicate of #607

henribru commented 2 years ago

@AlexWaygood This isn't a duplicate, no_type_check and type_check_only are different things. Please reopen this.

AlexWaygood commented 2 years ago

@AlexWaygood This isn't a duplicate, no_type_check and type_check_only are different things. Please reopen this.

Sorry, my bad, I misread!