From a5c83cbd2470bc7e0546947788236d1382248adc Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 14:58:17 -0400 Subject: [PATCH 1/7] Ensure that it fails --- stdlib/@tests/test_cases/check_os_path.py | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 stdlib/@tests/test_cases/check_os_path.py diff --git a/stdlib/@tests/test_cases/check_os_path.py b/stdlib/@tests/test_cases/check_os_path.py new file mode 100644 index 000000000000..821e66631255 --- /dev/null +++ b/stdlib/@tests/test_cases/check_os_path.py @@ -0,0 +1,28 @@ +from __future__ import annotations +from _typeshed import StrOrBytesPath +from os import PathLike +from os.path import abspath, expanduser, expandvars +from typing_extensions import assert_type +from typing import Union + + +def test_str_path(str_path: StrOrBytesPath) -> None: + # Ensures that these methods still work with a StrOrBytesPath + # They were overloaded to work around python/mypy#3644 + # But removing the overloads workaround still breaks usage + + assert_type(abspath(str_path), Union[str, bytes]) + assert_type(expanduser(str_path), Union[str, bytes]) + assert_type(expandvars(str_path), Union[str, bytes]) + + +class MyPath(PathLike): + def __init__(self, path: str | bytes): + super().__init__() + self.path = path + + def __fspath__(self) -> str | bytes: + return self.path + + +abspath(MyPath(".")) From c20556e6dada884874e63f6972044bba9faa308f Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:09:29 -0400 Subject: [PATCH 2/7] More complete test --- stdlib/@tests/test_cases/check_os_path.py | 38 ++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/stdlib/@tests/test_cases/check_os_path.py b/stdlib/@tests/test_cases/check_os_path.py index 821e66631255..c27d4d297903 100644 --- a/stdlib/@tests/test_cases/check_os_path.py +++ b/stdlib/@tests/test_cases/check_os_path.py @@ -3,7 +3,7 @@ from os import PathLike from os.path import abspath, expanduser, expandvars from typing_extensions import assert_type -from typing import Union +from typing import AnyStr, Union def test_str_path(str_path: StrOrBytesPath) -> None: @@ -16,8 +16,9 @@ def test_str_path(str_path: StrOrBytesPath) -> None: assert_type(expandvars(str_path), Union[str, bytes]) -class MyPath(PathLike): - def __init__(self, path: str | bytes): +# See https://github.com/python/mypy/issues/17952 +class MyPathMissingGeneric(PathLike): # pyright: ignore[reportMissingTypeArgument] # Explicitly testing w/ missing type argument + def __init__(self, path: str | bytes) -> None: super().__init__() self.path = path @@ -25,4 +26,33 @@ def __fspath__(self) -> str | bytes: return self.path -abspath(MyPath(".")) +# MyPathMissingGeneric could also be fixed by users by adding the missing generic annotation +class MyPathGeneric(PathLike[AnyStr]): + def __init__(self, path: AnyStr) -> None: + super().__init__() + self.path: AnyStr = path + + def __fspath__(self) -> AnyStr: + return self.path + + +class MyPathStr(PathLike[str]): + def __init__(self, path: str) -> None: + super().__init__() + self.path = path + + def __fspath__(self) -> str: + return self.path + + +abspath(MyPathMissingGeneric(".")) +expanduser(MyPathMissingGeneric(".")) +expandvars(MyPathMissingGeneric(".")) + +abspath(MyPathGeneric(".")) +expanduser(MyPathGeneric(".")) +expandvars(MyPathGeneric(".")) + +abspath(MyPathStr(".")) +expanduser(MyPathStr(".")) +expandvars(MyPathStr(".")) From 66472ec9854a48d7c2c7feab00017bdd90996393 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:13:45 -0400 Subject: [PATCH 3/7] Revert "Remove obsolete mypy bug workaround in `abspath()` (#12208)" This reverts commit 271df8ef040500e3dc4d3ca6be50eea7bd07bc62. --- stdlib/posixpath.pyi | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/stdlib/posixpath.pyi b/stdlib/posixpath.pyi index 31406f8df950..e5f5fa0d813c 100644 --- a/stdlib/posixpath.pyi +++ b/stdlib/posixpath.pyi @@ -77,7 +77,11 @@ pathsep: LiteralString defpath: LiteralString devnull: LiteralString -def abspath(path: PathLike[AnyStr] | AnyStr) -> AnyStr: ... +# Overloads are necessary to work around python/mypy#3644. +@overload +def abspath(path: PathLike[AnyStr]) -> AnyStr: ... +@overload +def abspath(path: AnyStr) -> AnyStr: ... @overload def basename(p: PathLike[AnyStr]) -> AnyStr: ... @overload @@ -86,8 +90,14 @@ def basename(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... def dirname(p: PathLike[AnyStr]) -> AnyStr: ... @overload def dirname(p: AnyOrLiteralStr) -> AnyOrLiteralStr: ... -def expanduser(path: PathLike[AnyStr] | AnyStr) -> AnyStr: ... -def expandvars(path: PathLike[AnyStr] | AnyStr) -> AnyStr: ... +@overload +def expanduser(path: PathLike[AnyStr]) -> AnyStr: ... +@overload +def expanduser(path: AnyStr) -> AnyStr: ... +@overload +def expandvars(path: PathLike[AnyStr]) -> AnyStr: ... +@overload +def expandvars(path: AnyStr) -> AnyStr: ... @overload def normcase(s: PathLike[AnyStr]) -> AnyStr: ... @overload From 4957845c0a4fb11703fbfe62dc37db2df6ab67b8 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:15:15 -0400 Subject: [PATCH 4/7] Add comment referencing new PR --- stdlib/posixpath.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/posixpath.pyi b/stdlib/posixpath.pyi index e5f5fa0d813c..a3269bea7ccb 100644 --- a/stdlib/posixpath.pyi +++ b/stdlib/posixpath.pyi @@ -77,7 +77,8 @@ pathsep: LiteralString defpath: LiteralString devnull: LiteralString -# Overloads are necessary to work around python/mypy#3644. +# Overloads were necessary to work around python/mypy#3644. +# See python/typeshed#12837 as to why they're still needed. @overload def abspath(path: PathLike[AnyStr]) -> AnyStr: ... @overload From 4149b098215d7a1bbd000b937027579a14b37ffb Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:23:22 -0400 Subject: [PATCH 5/7] Explicitly testing w/ missing type argument --- stdlib/@tests/test_cases/check_os_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/@tests/test_cases/check_os_path.py b/stdlib/@tests/test_cases/check_os_path.py index c27d4d297903..294c57e2ba2e 100644 --- a/stdlib/@tests/test_cases/check_os_path.py +++ b/stdlib/@tests/test_cases/check_os_path.py @@ -17,7 +17,7 @@ def test_str_path(str_path: StrOrBytesPath) -> None: # See https://github.com/python/mypy/issues/17952 -class MyPathMissingGeneric(PathLike): # pyright: ignore[reportMissingTypeArgument] # Explicitly testing w/ missing type argument +class MyPathMissingGeneric(PathLike): # type: ignore # Explicitly testing w/ missing type argument def __init__(self, path: str | bytes) -> None: super().__init__() self.path = path From 4ebd22b240ddcf8e68ef895f6da405021cb93019 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:35:48 -0400 Subject: [PATCH 6/7] Update comments --- stdlib/@tests/test_cases/check_os_path.py | 7 +++---- stdlib/posixpath.pyi | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/stdlib/@tests/test_cases/check_os_path.py b/stdlib/@tests/test_cases/check_os_path.py index 294c57e2ba2e..aeec873fbef0 100644 --- a/stdlib/@tests/test_cases/check_os_path.py +++ b/stdlib/@tests/test_cases/check_os_path.py @@ -7,16 +7,15 @@ def test_str_path(str_path: StrOrBytesPath) -> None: - # Ensures that these methods still work with a StrOrBytesPath - # They were overloaded to work around python/mypy#3644 - # But removing the overloads workaround still breaks usage + # These methods are currently overloaded to work around python/mypy#17952 & python/mypy#11880 + # Let's ensure that they'll still work with a StrOrBytesPath if the workaround is removed assert_type(abspath(str_path), Union[str, bytes]) assert_type(expanduser(str_path), Union[str, bytes]) assert_type(expandvars(str_path), Union[str, bytes]) -# See https://github.com/python/mypy/issues/17952 +# See python/mypy#17952 class MyPathMissingGeneric(PathLike): # type: ignore # Explicitly testing w/ missing type argument def __init__(self, path: str | bytes) -> None: super().__init__() diff --git a/stdlib/posixpath.pyi b/stdlib/posixpath.pyi index a3269bea7ccb..3089025e8624 100644 --- a/stdlib/posixpath.pyi +++ b/stdlib/posixpath.pyi @@ -77,8 +77,7 @@ pathsep: LiteralString defpath: LiteralString devnull: LiteralString -# Overloads were necessary to work around python/mypy#3644. -# See python/typeshed#12837 as to why they're still needed. +# Overloads were necessary to work around python/mypy#17952 & python/mypy#11880 @overload def abspath(path: PathLike[AnyStr]) -> AnyStr: ... @overload From 53fa5bafa4572d44d74bde5d56329dec2ec9c5f2 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 17 Oct 2024 15:38:29 -0400 Subject: [PATCH 7/7] typo --- stdlib/posixpath.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/posixpath.pyi b/stdlib/posixpath.pyi index 3089025e8624..3313667f1781 100644 --- a/stdlib/posixpath.pyi +++ b/stdlib/posixpath.pyi @@ -77,7 +77,7 @@ pathsep: LiteralString defpath: LiteralString devnull: LiteralString -# Overloads were necessary to work around python/mypy#17952 & python/mypy#11880 +# Overloads are necessary to work around python/mypy#17952 & python/mypy#11880 @overload def abspath(path: PathLike[AnyStr]) -> AnyStr: ... @overload