Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return value from os.fspath for non-string arguments #4844

Closed
matthewhughes934 opened this issue Dec 20, 2020 · 2 comments
Closed

Return value from os.fspath for non-string arguments #4844

matthewhughes934 opened this issue Dec 20, 2020 · 2 comments

Comments

@matthewhughes934
Copy link
Contributor

From its docs os.fspath can take any os.PathLike object but must return either str or bytes. However, typeshed appears to only support str, bytes, or PathLike[AnyStr] (from here). Would a new overload be appropriate here? Like:

def fspath(path: PathLike[Any]) -> AnyStr: ...

Example:

import os

def get_path(path: object) -> str:
    if isinstance(path, os.PathLike):
        path_repr = os.fspath(path)
        reveal_type(path_repr)
        if isinstance(path_repr, bytes):
            return path_repr.decode("UTF-8")
        else:
            return path_repr
    else:
        raise Exception("I don't know what to do with this")
$ mypy --warn-return-any --custom-typeshed-dir ~/src/typeshed/ type.py 
type.py:6: note: Revealed type is 'Any'
type.py:10: error: Returning Any from function declared to return "str"
Found 1 error in 1 file (checked 1 source file)

(I understand mypy != typeshed, but wasn't sure of a better way to give an example)

I'm not terribly well versed with typeshed/the deeper details of typing in general, so apologies if I'm completely misunderstanding anything.

@hauntsaninja
Copy link
Collaborator

Adding your overload doesn't change the result of type checking for me, does it for you? (Asking because I see you used --custom-typeshed-dir in your command)

This is a case where gradual typing / "Any turns the type checker off" is suboptimal for some use cases. E.g., when matching def fspath(path: PathLike[AnyStr]) -> AnyStr: ... to PathLike[Any], mypy could probably infer the return type as Union[str, bytes], based on the value restriction of the AnyStr typevar, but instead it propagates the Any.

This is great for gradual typing, but it looks like in your case you'd prefer the Union return that you can pick apart at your leisure. (A bit of an in between would be if we added something like python/typing#566, mypy could use those kind of semantics for it. In fact, some people have suggested using a value restricted typevar as a way to spell this).

I don't think there's any overload typeshed could add that would do what you want (and I'm not sure we'd accept it if there was one), so I'm closing. Note a workaround for your mypy error is to add an if isinstance(path_repr, str) before your second return (and throw an exception otherwise).

@matthewhughes934
Copy link
Contributor Author

Thanks for all the info!

Adding your overload doesn't change the result of type checking for me, does it for you?

Ah, my quick and dirty test was actually to change the existing overload (which I imagine is far from acceptable). If I add the overload instead I see the same result as you: result of type checking is unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants