tox-dev / platformdirs

A small Python module for determining appropriate platform-specific dirs, e.g. a "user data dir".
https://platformdirs.readthedocs.io
MIT License
568 stars 49 forks source link

Ensure PlatformDirs is valid superclass type for mypy AND not an abstract class for other checkers #295

Closed Avasam closed 3 weeks ago

Avasam commented 1 month ago

This was spotted in https://github.com/jaraco/jaraco.abode/blob/8843f360ee5d9bc1afb1bdb3119157addb4aaf06/jaraco/abode/config.py#L4C7-L4C19 / https://github.com/jaraco/skeleton/pull/136#issuecomment-2303602369

Trying to subclass PlatformDirs (and by extension, AppDirs) results in the following error with mypy: Variable "platformdirs.PlatformDirs" is not valid as a type This is a known issue: https://github.com/python/mypy/issues/10962

Thankfully it can be worked around, which this PR does, as well as adding a static test for it.


Then another issue is revealed, since PlatformDirs is typed as being an abstract class, it shouldn't be allowed to be instantiated ! So I can't just do:

if TYPE_CHECKING:
    # Work around mypy issue: https://github.com/python/mypy/issues/10962
    PlatformDirs: TypeAlias = PlatformDirsABC
else:
    PlatformDirs = _set_platform_dir_class()  #: Currently active platform

I'm honnestly a bit dumbofunded by that one. It's a perfect unfixeable storm.

I can't type PlatformDirs as a TypeAlias of type[Result] | type[Android] because we're right back to square one. And without https://peps.python.org/pep-0738/ I can't just alias PlatformDirs to Result otherwise if PlatformDirs is Android will always be raised as an issue by type_checkers. Same if I make PlatformDirs a fake subclass of PlatformDirsABC in the TYPE_CHECKING block.

I think the false positive on if PlatformDirs is Android is probably much better than a false positive on class MySubclass(PlatformDirs): ... So I'll go for that.

Avasam commented 1 month ago

The doc test doesn't like typing_extensions import. WARNING: Failed guarded type import with ModuleNotFoundError("No module named 'typing_extensions'") I guess that's because it's not installed in whatever doc making environment.

Thankfully TypeAlias is not needed for this fix, so I'll omit it