typeshed icon indicating copy to clipboard operation
typeshed copied to clipboard

Underscore for type-check only items?

Open srittau opened this issue 2 years ago • 4 comments

Just a random thought: When we add classes or type aliases to stubs that aren't available at runtime, but could be useful for users as well (by using if TYPE_CHECKING:), we currently prefix them with an underscore. This has two disadvantages:

  1. Linters and IDEs (as well as the linter in my brain) often mark them as "using a private item from an external module". This isn't really the case here as we support the use of these items during type checking.
  2. It doesn't really communicate the fact that the item is available during type-check only.

Maybe it would make sense to come up with another convention to mark these type-check only? The (admittedly failed) @type_check_only decorator doesn't really help in this situation, as it marks the items only when defining them, not when importing them. It also doesn't work with type aliases.

srittau avatar Dec 08 '23 11:12 srittau

I think we need to make sure we continue to clearly signal "danger" to users with these aliases. Importing things under if TYPE_CHECKING blocks can be useful, but it's not something typing beginners will necessarily know about. I think it would be a bad outcome if IDEs and autocomplete tools started recommending to users that they imported apparently public-API aliases etc., with neither the tool nor the user realising that the aliases weren't available at runtime.

So: I'm open to changes, but think we need to be cautious and make sure we don't regress on user experience for people who don't know about typeshed etc. :)

AlexWaygood avatar Dec 08 '23 11:12 AlexWaygood

I also think stubtest could help us here for the @type_check_only decorator (even though it's limited, I also wish some decorators in Python worked on more than just callables): https://github.com/python/mypy/issues/15146

Avasam avatar Dec 08 '23 15:12 Avasam

Not sure if I like this idea or not, but I'll share it anyway to get it out: If you place all non-runtime typing into a single private module in a package, type-checkers may warn about private module usage, and may warn about the module not existing at runtime (reportMissingModuleSource in pyright). Example usage from AutoSplit using pywin32 (this is a special case module for types defined in the C extension but never exposed to the Python interface): image

If you use a standard name (like _type_check_only or _typeshed_type_check_only), you can also configure tooling to ignore specific rules in there with per-file/per-folder ignore (like Y047)

Might cause a lot of cross-reference, and specialized aliases/Protocols/etc won't live in the only place they're used. Some context might be lost.

Avasam avatar Dec 08 '23 18:12 Avasam

Currently we have _typeshed. What about expanding that? I'd suggest that for a given stdlib module foo we should import from _typeshed.foo while for a third-party module bar we should import from bar._typeshed.

My thinking there is that most stdlib modules are single-file, and it'd be a pain to convert them all to a directory just for this. But on the other hand, putting all the third-party modules under _typeshed.* would be breaking the context more than necessary, and maybe be a little crowded

tungol avatar Dec 16 '23 02:12 tungol