From dad5349e4ca47abc18c2b9d6c161644f6bbaeecb Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 21 Nov 2024 22:56:45 -0800 Subject: [PATCH 01/16] fix the length of platform.uname_result It should be a 6-tuple, once processor is added. This makes sure mypy understands that. Fixes https://github.com/python/typeshed/issues/13064 --- stdlib/platform.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index fcb5b005650f..2365ba25b7e0 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -23,7 +23,7 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base): + class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): @property def processor(self) -> str: ... From 934266aec7126908a28b31aefdd1090de820c32b Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Fri, 22 Nov 2024 00:02:06 -0800 Subject: [PATCH 02/16] ignore --- stdlib/platform.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 2365ba25b7e0..1d489515ad41 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -23,7 +23,7 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): + class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): # type: ignore[misc] @property def processor(self) -> str: ... From ca05fd0695e2eefb4d2d6c83d361dbc1945733c6 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Fri, 22 Nov 2024 00:12:12 -0800 Subject: [PATCH 03/16] pyright --- stdlib/platform.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 1d489515ad41..337b784652bf 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -23,7 +23,7 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): # type: ignore[misc] + class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] @property def processor(self) -> str: ... From ef411cd39d87c774086b78002ec1008af81c3e85 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Fri, 22 Nov 2024 11:47:03 -0800 Subject: [PATCH 04/16] add test case and comments --- stdlib/@tests/test_cases/check_platform.py | 19 +++++++++++++++++++ stdlib/platform.pyi | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 stdlib/@tests/test_cases/check_platform.py diff --git a/stdlib/@tests/test_cases/check_platform.py b/stdlib/@tests/test_cases/check_platform.py new file mode 100644 index 000000000000..efcbd992c90b --- /dev/null +++ b/stdlib/@tests/test_cases/check_platform.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +import platform +import sys +from typing_extensions import assert_type + +# platform.uname_result emulates a 6 field named tuple, but on 3.9+ the processor +# field is lazily evaluated, which results in it being a little funky. +uname = platform.uname() +if sys.version_info >= (3, 9): + myuname = platform.uname_result("Darwin", "local", "22.5.0", "Darwin Kernel Version 22.5.0", "arm64") +else: + myuname = platform.uname_result("Darwin", "local", "22.5.0", "Darwin Kernel Version 22.5.0", "arm64", "arm") + +assert_type(uname, platform.uname_result) +assert_type(myuname, platform.uname_result) + +assert_type(uname[5], str) +assert_type(myuname[5], str) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 337b784652bf..2784da48b897 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -15,6 +15,8 @@ def system_alias(system: str, release: str, version: str) -> tuple[str, str, str def architecture(executable: str = sys.executable, bits: str = "", linkage: str = "") -> tuple[str, str]: ... if sys.version_info >= (3, 9): + # uname_result emulates a 6-field named tuple, but the processor field + # is lazily evaluated rather than being passed in to the constructor. @type_check_only class _uname_result_base(NamedTuple): system: str From 9a5deacc7ccd6d301d8dec4cfad9089bef1f36f0 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 02:31:40 -0800 Subject: [PATCH 05/16] try a different strategy --- stdlib/platform.pyi | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 2784da48b897..389c0188585b 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -25,9 +25,14 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base, tuple[str, str, str, str, str, str]): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] - @property - def processor(self) -> str: ... + class uname_result(_uname_result_base, NamedTuple): # pyright: ignore[reportGeneralTypeIssues] + system: str + node: str + release: str + version: str + machine: str + processor: str + def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... else: class uname_result(NamedTuple): From da8d5515530b12d6818386f0802f0b913f881229 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 02:45:39 -0800 Subject: [PATCH 06/16] fixes? --- stdlib/platform.pyi | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 389c0188585b..82e12b60e752 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -1,5 +1,6 @@ import sys -from typing import NamedTuple, type_check_only +from typing import Literal, NamedTuple, type_check_only +from typing_extensions import Self def libc_ver(executable: str | None = None, lib: str = "", version: str = "", chunksize: int = 16384) -> tuple[str, str]: ... def win32_ver(release: str = "", version: str = "", csd: str = "", ptype: str = "") -> tuple[str, str, str, str]: ... @@ -25,14 +26,20 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base, NamedTuple): # pyright: ignore[reportGeneralTypeIssues] + class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] system: str node: str release: str version: str machine: str - processor: str - def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... + extra: str + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] + @property + def __match_args__( + self, + ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + @property + def processor(self) -> str: ... else: class uname_result(NamedTuple): From 9c3479bd38527a611228d3ce42caa2f8a63cdc84 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 02:49:04 -0800 Subject: [PATCH 07/16] _fields for 3.9 --- stdlib/platform.pyi | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 82e12b60e752..6ef531e4a8d4 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -34,10 +34,17 @@ if sys.version_info >= (3, 9): machine: str extra: str def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - @property - def __match_args__( - self, - ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + if sys.version_info >= (3, 10): + @property + def __match_args__( + self, + ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + else: + @property + def _fields( + self, + ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + @property def processor(self) -> str: ... From b16ee65742a57f2d88f9e91f6ffbbaf6c2bf508a Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 02:54:22 -0800 Subject: [PATCH 08/16] tweak again --- stdlib/platform.pyi | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 6ef531e4a8d4..1f966daa0728 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -26,27 +26,37 @@ if sys.version_info >= (3, 9): version: str machine: str - class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] - system: str - node: str - release: str - version: str - machine: str - extra: str - def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - if sys.version_info >= (3, 10): + if sys.version_info >= (3, 10): + class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + system: str + node: str + release: str + version: str + machine: str + extra: str + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] @property def __match_args__( self, ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... - else: @property + def processor(self) -> str: ... + + else: + class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + system: str + node: str + release: str + version: str + machine: str + extra: str + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] + @property # type: ignore[misc] def _fields( self, ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... - - @property - def processor(self) -> str: ... + @property + def processor(self) -> str: ... else: class uname_result(NamedTuple): From 836c50a4848bae903b1fa5f1edd945c0a2a7acd0 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 03:01:34 -0800 Subject: [PATCH 09/16] don't try to make processor a property --- stdlib/@tests/stubtest_allowlists/py310.txt | 1 + stdlib/@tests/stubtest_allowlists/py311.txt | 1 + stdlib/@tests/stubtest_allowlists/py312.txt | 1 + stdlib/@tests/stubtest_allowlists/py313.txt | 1 + stdlib/@tests/stubtest_allowlists/py39.txt | 1 + stdlib/platform.pyi | 10 ++++------ 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py310.txt b/stdlib/@tests/stubtest_allowlists/py310.txt index 1c4ce9bb30dd..db5d56aa0624 100644 --- a/stdlib/@tests/stubtest_allowlists/py310.txt +++ b/stdlib/@tests/stubtest_allowlists/py310.txt @@ -25,6 +25,7 @@ lib2to3.pytree.BasePattern.type lib2to3.pytree.NegatedPattern.match lib2to3.pytree.NegatedPattern.match_seq lib2to3.pgen2.grammar.Grammar.loads +platform.uname_result.processor tkinter.Tk.split tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion diff --git a/stdlib/@tests/stubtest_allowlists/py311.txt b/stdlib/@tests/stubtest_allowlists/py311.txt index 5ec3fc926602..a61f5f4b1307 100644 --- a/stdlib/@tests/stubtest_allowlists/py311.txt +++ b/stdlib/@tests/stubtest_allowlists/py311.txt @@ -25,6 +25,7 @@ lib2to3.btm_utils lib2to3.fixer_util lib2to3.patcomp lib2to3.pgen2.grammar.Grammar.loads +platform.uname_result.processor tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion tkinter.tix.TkVersion diff --git a/stdlib/@tests/stubtest_allowlists/py312.txt b/stdlib/@tests/stubtest_allowlists/py312.txt index 486dd518909f..ac8ff471c058 100644 --- a/stdlib/@tests/stubtest_allowlists/py312.txt +++ b/stdlib/@tests/stubtest_allowlists/py312.txt @@ -22,6 +22,7 @@ lib2to3.btm_utils lib2to3.fixer_util lib2to3.patcomp lib2to3.pgen2.grammar.Grammar.loads +platform.uname_result.processor tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion tkinter.tix.TkVersion diff --git a/stdlib/@tests/stubtest_allowlists/py313.txt b/stdlib/@tests/stubtest_allowlists/py313.txt index 6de58d2a82dc..ef2ec75fe7ae 100644 --- a/stdlib/@tests/stubtest_allowlists/py313.txt +++ b/stdlib/@tests/stubtest_allowlists/py313.txt @@ -42,6 +42,7 @@ enum.Enum.__init__ importlib._abc.Loader.exec_module # See Lib/importlib/_abc.py. Might be defined for backwards compatibility typing.NewType.__mro_entries__ builtins.ellipsis # type is not exposed anywhere +platform.uname_result.processor # ========== # Related to positional-only arguments diff --git a/stdlib/@tests/stubtest_allowlists/py39.txt b/stdlib/@tests/stubtest_allowlists/py39.txt index bf7d7461dbb1..3b367e9c3582 100644 --- a/stdlib/@tests/stubtest_allowlists/py39.txt +++ b/stdlib/@tests/stubtest_allowlists/py39.txt @@ -39,6 +39,7 @@ lib2to3.pytree.BasePattern.type lib2to3.pytree.NegatedPattern.match lib2to3.pytree.NegatedPattern.match_seq lib2to3.pgen2.grammar.Grammar.loads +platform.uname_result.processor tkinter.Tk.split tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 1f966daa0728..7e569e49429c 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -33,14 +33,13 @@ if sys.version_info >= (3, 9): release: str version: str machine: str - extra: str + processor: str # actually a property + def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] @property def __match_args__( self, ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... - @property - def processor(self) -> str: ... else: class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] @@ -49,14 +48,13 @@ if sys.version_info >= (3, 9): release: str version: str machine: str - extra: str + processor: str # actually a property + def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] @property # type: ignore[misc] def _fields( self, ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... - @property - def processor(self) -> str: ... else: class uname_result(NamedTuple): From 4c2ed2d7f7a3145a85c3e60e64f680bc1edaea3e Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 03:18:39 -0800 Subject: [PATCH 10/16] base order --- stdlib/platform.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 7e569e49429c..f493573fb6e8 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -27,7 +27,7 @@ if sys.version_info >= (3, 9): machine: str if sys.version_info >= (3, 10): - class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + class uname_result(NamedTuple, _uname_result_base): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] system: str node: str release: str @@ -42,7 +42,7 @@ if sys.version_info >= (3, 9): ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... else: - class uname_result(_uname_result_base, NamedTuple): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + class uname_result(NamedTuple, _uname_result_base): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] system: str node: str release: str From 9bc925715ae1c6a31718f168d91ca7addb390c12 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 14:53:33 -0800 Subject: [PATCH 11/16] don't bother with _uname_result_base --- stdlib/platform.pyi | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index f493573fb6e8..9836ccc358fa 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -1,5 +1,5 @@ import sys -from typing import Literal, NamedTuple, type_check_only +from typing import Literal, NamedTuple from typing_extensions import Self def libc_ver(executable: str | None = None, lib: str = "", version: str = "", chunksize: int = 16384) -> tuple[str, str]: ... @@ -18,16 +18,8 @@ def architecture(executable: str = sys.executable, bits: str = "", linkage: str if sys.version_info >= (3, 9): # uname_result emulates a 6-field named tuple, but the processor field # is lazily evaluated rather than being passed in to the constructor. - @type_check_only - class _uname_result_base(NamedTuple): - system: str - node: str - release: str - version: str - machine: str - if sys.version_info >= (3, 10): - class uname_result(NamedTuple, _uname_result_base): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + class uname_result(NamedTuple): system: str node: str release: str @@ -42,7 +34,7 @@ if sys.version_info >= (3, 9): ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... else: - class uname_result(NamedTuple, _uname_result_base): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] + class uname_result(NamedTuple): system: str node: str release: str From d850b0bf2bf210d704146f61fa647ebf6d4da1cf Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Sun, 24 Nov 2024 14:57:28 -0800 Subject: [PATCH 12/16] flatten and update comments --- stdlib/platform.pyi | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 9836ccc358fa..f7d7047464e2 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -15,40 +15,46 @@ def java_ver( def system_alias(system: str, release: str, version: str) -> tuple[str, str, str]: ... def architecture(executable: str = sys.executable, bits: str = "", linkage: str = "") -> tuple[str, str]: ... -if sys.version_info >= (3, 9): +if sys.version_info >= (3, 10): # uname_result emulates a 6-field named tuple, but the processor field # is lazily evaluated rather than being passed in to the constructor. - if sys.version_info >= (3, 10): - class uname_result(NamedTuple): - system: str - node: str - release: str - version: str - machine: str - processor: str # actually a property - def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] - def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - @property - def __match_args__( - self, - ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + # At runtime, it inherits from a 5-field NamedTuple instead of being a + # NamedTuple itself, but that's too hacky to represent in the stubs. + class uname_result(NamedTuple): + system: str + node: str + release: str + version: str + machine: str + processor: str # actually a property + def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] + @property + def __match_args__( + self, + ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... - else: - class uname_result(NamedTuple): - system: str - node: str - release: str - version: str - machine: str - processor: str # actually a property - def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] - def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - @property # type: ignore[misc] - def _fields( - self, - ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... +elif sys.version_info >= (3, 9): + # uname_result emulates a 6-field named tuple, but the processor field + # is lazily evaluated rather than being passed in to the constructor. + # At runtime, it inherits from a 5-field NamedTuple instead of being a + # NamedTuple itself, but that's too hacky to represent in the stubs. + class uname_result(NamedTuple): + system: str + node: str + release: str + version: str + machine: str + processor: str # actually a property + def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] + @property # type: ignore[misc] + def _fields( + self, + ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... else: + # On 3.8, uname_result is actually just a regular NamedTuple. class uname_result(NamedTuple): system: str node: str From dea21c673ce7d154d87108fec6de4c974b5844e6 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 25 Nov 2024 10:54:41 -0800 Subject: [PATCH 13/16] bring back _uname_result_base --- stdlib/@tests/stubtest_allowlists/py310.txt | 1 - stdlib/@tests/stubtest_allowlists/py311.txt | 1 - stdlib/@tests/stubtest_allowlists/py312.txt | 1 - stdlib/@tests/stubtest_allowlists/py313.txt | 1 - stdlib/@tests/stubtest_allowlists/py39.txt | 1 - stdlib/platform.pyi | 47 ++++++++------------- 6 files changed, 17 insertions(+), 35 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py310.txt b/stdlib/@tests/stubtest_allowlists/py310.txt index db5d56aa0624..1c4ce9bb30dd 100644 --- a/stdlib/@tests/stubtest_allowlists/py310.txt +++ b/stdlib/@tests/stubtest_allowlists/py310.txt @@ -25,7 +25,6 @@ lib2to3.pytree.BasePattern.type lib2to3.pytree.NegatedPattern.match lib2to3.pytree.NegatedPattern.match_seq lib2to3.pgen2.grammar.Grammar.loads -platform.uname_result.processor tkinter.Tk.split tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion diff --git a/stdlib/@tests/stubtest_allowlists/py311.txt b/stdlib/@tests/stubtest_allowlists/py311.txt index a61f5f4b1307..5ec3fc926602 100644 --- a/stdlib/@tests/stubtest_allowlists/py311.txt +++ b/stdlib/@tests/stubtest_allowlists/py311.txt @@ -25,7 +25,6 @@ lib2to3.btm_utils lib2to3.fixer_util lib2to3.patcomp lib2to3.pgen2.grammar.Grammar.loads -platform.uname_result.processor tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion tkinter.tix.TkVersion diff --git a/stdlib/@tests/stubtest_allowlists/py312.txt b/stdlib/@tests/stubtest_allowlists/py312.txt index ac8ff471c058..486dd518909f 100644 --- a/stdlib/@tests/stubtest_allowlists/py312.txt +++ b/stdlib/@tests/stubtest_allowlists/py312.txt @@ -22,7 +22,6 @@ lib2to3.btm_utils lib2to3.fixer_util lib2to3.patcomp lib2to3.pgen2.grammar.Grammar.loads -platform.uname_result.processor tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion tkinter.tix.TkVersion diff --git a/stdlib/@tests/stubtest_allowlists/py313.txt b/stdlib/@tests/stubtest_allowlists/py313.txt index ef2ec75fe7ae..6de58d2a82dc 100644 --- a/stdlib/@tests/stubtest_allowlists/py313.txt +++ b/stdlib/@tests/stubtest_allowlists/py313.txt @@ -42,7 +42,6 @@ enum.Enum.__init__ importlib._abc.Loader.exec_module # See Lib/importlib/_abc.py. Might be defined for backwards compatibility typing.NewType.__mro_entries__ builtins.ellipsis # type is not exposed anywhere -platform.uname_result.processor # ========== # Related to positional-only arguments diff --git a/stdlib/@tests/stubtest_allowlists/py39.txt b/stdlib/@tests/stubtest_allowlists/py39.txt index 3b367e9c3582..bf7d7461dbb1 100644 --- a/stdlib/@tests/stubtest_allowlists/py39.txt +++ b/stdlib/@tests/stubtest_allowlists/py39.txt @@ -39,7 +39,6 @@ lib2to3.pytree.BasePattern.type lib2to3.pytree.NegatedPattern.match lib2to3.pytree.NegatedPattern.match_seq lib2to3.pgen2.grammar.Grammar.loads -platform.uname_result.processor tkinter.Tk.split tkinter.tix.[A-Z_]+ tkinter.tix.TclVersion diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index f7d7047464e2..682a08093a3e 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -1,5 +1,5 @@ import sys -from typing import Literal, NamedTuple +from typing import NamedTuple, type_check_only from typing_extensions import Self def libc_ver(executable: str | None = None, lib: str = "", version: str = "", chunksize: int = 16384) -> tuple[str, str]: ... @@ -15,43 +15,30 @@ def java_ver( def system_alias(system: str, release: str, version: str) -> tuple[str, str, str]: ... def architecture(executable: str = sys.executable, bits: str = "", linkage: str = "") -> tuple[str, str]: ... -if sys.version_info >= (3, 10): +if sys.version_info >= (3, 9): # uname_result emulates a 6-field named tuple, but the processor field # is lazily evaluated rather than being passed in to the constructor. - # At runtime, it inherits from a 5-field NamedTuple instead of being a - # NamedTuple itself, but that's too hacky to represent in the stubs. - class uname_result(NamedTuple): + # This class is not exposed. It calls itself platform.uname_result_base. + # At runtime it only has 5 fields. + @type_check_only + class _uname_result_base(NamedTuple): system: str node: str release: str version: str machine: str - processor: str # actually a property - def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] - def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - @property - def __match_args__( - self, - ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + # This base class doesn't have this field at runtime, but claiming it + # does is the least bad way to handle the situation. Nobody really + # sees this class anyway. + processor: str -elif sys.version_info >= (3, 9): - # uname_result emulates a 6-field named tuple, but the processor field - # is lazily evaluated rather than being passed in to the constructor. - # At runtime, it inherits from a 5-field NamedTuple instead of being a - # NamedTuple itself, but that's too hacky to represent in the stubs. - class uname_result(NamedTuple): - system: str - node: str - release: str - version: str - machine: str - processor: str # actually a property - def __init__(self, system: str, node: str, release: str, version: str, machine: str) -> None: ... # type: ignore[misc] - def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... # type: ignore[misc] - @property # type: ignore[misc] - def _fields( - self, - ) -> tuple[Literal["system"], Literal["node"], Literal["release"], Literal["version"], Literal["machine"]]: ... + class uname_result(_uname_result_base): + if sys.version_info >= (3, 10): + __match_args__ = ("system", "node", "release", "version", "machine") + + def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... + @property + def processor(self) -> str: ... else: # On 3.8, uname_result is actually just a regular NamedTuple. From f53f85dd5370bbf596bbce7e1006596eb370287f Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 25 Nov 2024 10:56:58 -0800 Subject: [PATCH 14/16] pyright --- stdlib/platform.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 682a08093a3e..8fca01987535 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -34,7 +34,7 @@ if sys.version_info >= (3, 9): class uname_result(_uname_result_base): if sys.version_info >= (3, 10): - __match_args__ = ("system", "node", "release", "version", "machine") + __match_args__ = ("system", "node", "release", "version", "machine") # pyright: ignore[reportAssignmentType] def __new__(_cls, system: str, node: str, release: str, version: str, machine: str) -> Self: ... @property From 3f79f408e3bc0dd4b337c0b3f9bc5d8cec51dab1 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 25 Nov 2024 10:58:07 -0800 Subject: [PATCH 15/16] move the comment --- stdlib/platform.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 8fca01987535..2df843dc96ce 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -16,8 +16,6 @@ def system_alias(system: str, release: str, version: str) -> tuple[str, str, str def architecture(executable: str = sys.executable, bits: str = "", linkage: str = "") -> tuple[str, str]: ... if sys.version_info >= (3, 9): - # uname_result emulates a 6-field named tuple, but the processor field - # is lazily evaluated rather than being passed in to the constructor. # This class is not exposed. It calls itself platform.uname_result_base. # At runtime it only has 5 fields. @type_check_only @@ -32,6 +30,8 @@ if sys.version_info >= (3, 9): # sees this class anyway. processor: str + # uname_result emulates a 6-field named tuple, but the processor field + # is lazily evaluated rather than being passed in to the constructor. class uname_result(_uname_result_base): if sys.version_info >= (3, 10): __match_args__ = ("system", "node", "release", "version", "machine") # pyright: ignore[reportAssignmentType] From 63a6d1ae07fccef82b0570f06859aa2010db6906 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 25 Nov 2024 10:58:54 -0800 Subject: [PATCH 16/16] add reference ticket --- stdlib/platform.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/platform.pyi b/stdlib/platform.pyi index 2df843dc96ce..73393eada02c 100644 --- a/stdlib/platform.pyi +++ b/stdlib/platform.pyi @@ -27,7 +27,7 @@ if sys.version_info >= (3, 9): machine: str # This base class doesn't have this field at runtime, but claiming it # does is the least bad way to handle the situation. Nobody really - # sees this class anyway. + # sees this class anyway. See #13068 processor: str # uname_result emulates a 6-field named tuple, but the processor field