Skip to content

convert shutil._PathReturn to a type parameter? #13508

Closed

Description

@dpinol

Since shutil._PathReturn is defined as Any, it may hide type errors to mypy-like tools. E.g in the following code, mypy will not detect that f function is invoked with an str argument instead of a Path.

import shutil
from pathlib import Path


def f(p: Path) -> None:
    pass


def cp(target: str | Path) -> None:
    p = shutil.copy("/src", target)
    return f(p)

Activity

  1. srittau commented on Feb 17, 2025

    @srittau
    Collaborator

    Unfortunately, changing this to a union in the general case would mean that users would need to add isinstance checks to the returned value in many cases. That said, looking at the implementation of copy(), I think we could do better for some cases: For example, passing str or bytes as dst will always return the same type. We could reflect that and keep the Any return type only when passing in a PathLike.

    The best solution would be to fix the functions in the standard library to return consistent types, but that's out of scope for typeshed.

  2. dpinol commented on Feb 17, 2025

    @dpinol
    Author

    I understand, thanks

  3. Avasam commented on Apr 2, 2025

    @Avasam
    SponsorCollaborator

    Given that the return type would be StrPath (ie: str | PathLike[str]) and that we can return a str if dst: str and str | _T otherwise, I'd argue that's a fine union to return.

    Most cases of using a StrPath whether you actually have a str or a PathLike won't matter too much. If you do explicitly need a str after potentially passing a PathLike or explicitely need the same PathLike you passed, then you should really check the return here.

    And once again, in most cases, you can coerce the type (using str() or Path())

    >>> Path("")
    WindowsPath('.')
    >>> Path(Path())
    WindowsPath('.')
    >>> str(".")
    '.'
    >>> str(Path("."))
    '.'

    (this argument may not hold as well for bytespath though, what's a common PathLike[bytes] ?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stubs: improvementImprove/refactor existing annotations, other stubs issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions