From 3e08f92a00c6e597342a6c76a264bab4f988d2fd Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 30 Aug 2023 10:24:06 +0300 Subject: [PATCH 1/7] Add `durations` to `unittest` in 3.12 --- stdlib/unittest/main.pyi | 53 ++++++++++++++++++--------- stdlib/unittest/result.pyi | 7 ++++ stdlib/unittest/runner.pyi | 55 ++++++++++++++++++++++------- tests/stubtest_allowlists/py312.txt | 8 ----- 4 files changed, 86 insertions(+), 37 deletions(-) diff --git a/stdlib/unittest/main.pyi b/stdlib/unittest/main.pyi index 6d970c920096..686bf8bc444a 100644 --- a/stdlib/unittest/main.pyi +++ b/stdlib/unittest/main.pyi @@ -1,3 +1,4 @@ +import sys import unittest.case import unittest.loader import unittest.result @@ -23,22 +24,42 @@ class TestProgram: progName: str | None warnings: str | None testNamePatterns: list[str] | None - def __init__( - self, - module: None | str | ModuleType = "__main__", - defaultTest: str | Iterable[str] | None = None, - argv: list[str] | None = None, - testRunner: type[_TestRunner] | _TestRunner | None = None, - testLoader: unittest.loader.TestLoader = ..., - exit: bool = True, - verbosity: int = 1, - failfast: bool | None = None, - catchbreak: bool | None = None, - buffer: bool | None = None, - warnings: str | None = None, - *, - tb_locals: bool = False, - ) -> None: ... + if sys.version_info >= (3, 12): + durations: unittest.result._DurationsType | None + def __init__( + self, + module: None | str | ModuleType = "__main__", + defaultTest: str | Iterable[str] | None = None, + argv: list[str] | None = None, + testRunner: type[_TestRunner] | _TestRunner | None = None, + testLoader: unittest.loader.TestLoader = ..., + exit: bool = True, + verbosity: int = 1, + failfast: bool | None = None, + catchbreak: bool | None = None, + buffer: bool | None = None, + warnings: str | None = None, + *, + tb_locals: bool = False, + durations: unittest.result._DurationsType | None = None, + ) -> None: ... + else: + def __init__( + self, + module: None | str | ModuleType = "__main__", + defaultTest: str | Iterable[str] | None = None, + argv: list[str] | None = None, + testRunner: type[_TestRunner] | _TestRunner | None = None, + testLoader: unittest.loader.TestLoader = ..., + exit: bool = True, + verbosity: int = 1, + failfast: bool | None = None, + catchbreak: bool | None = None, + buffer: bool | None = None, + warnings: str | None = None, + *, + tb_locals: bool = False, + ) -> None: ... def usageExit(self, msg: Any = None) -> None: ... def parseArgs(self, argv: list[str]) -> None: ... def createTests(self, from_discovery: bool = False, Loader: unittest.loader.TestLoader | None = None) -> None: ... diff --git a/stdlib/unittest/result.pyi b/stdlib/unittest/result.pyi index 8d78bc0f7dcf..4ccf24d9c905 100644 --- a/stdlib/unittest/result.pyi +++ b/stdlib/unittest/result.pyi @@ -1,9 +1,12 @@ +import sys import unittest.case from _typeshed import OptExcInfo from collections.abc import Callable from typing import Any, TextIO, TypeVar +from typing_extensions import TypeAlias _F = TypeVar("_F", bound=Callable[..., Any]) +_DurationsType: TypeAlias = list[tuple[unittest.case.TestCase, float]] STDOUT_LINE: str STDERR_LINE: str @@ -22,6 +25,8 @@ class TestResult: buffer: bool failfast: bool tb_locals: bool + if sys.version_info >= (3, 12): + collectedDurations: _DurationsType def __init__(self, stream: TextIO | None = None, descriptions: bool | None = None, verbosity: int | None = None) -> None: ... def printErrors(self) -> None: ... def wasSuccessful(self) -> bool: ... @@ -37,3 +42,5 @@ class TestResult: def addExpectedFailure(self, test: unittest.case.TestCase, err: OptExcInfo) -> None: ... def addUnexpectedSuccess(self, test: unittest.case.TestCase) -> None: ... def addSubTest(self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: OptExcInfo | None) -> None: ... + if sys.version_info >= (3, 12): + def addDurations(self, test: unittest.case.TestCase, elapsed: float) -> None: ... diff --git a/stdlib/unittest/runner.pyi b/stdlib/unittest/runner.pyi index c0ddcdb49208..24acd4196a9e 100644 --- a/stdlib/unittest/runner.pyi +++ b/stdlib/unittest/runner.pyi @@ -1,3 +1,4 @@ +import sys import unittest.case import unittest.result import unittest.suite @@ -14,23 +15,51 @@ class TextTestResult(unittest.result.TestResult): separator2: str showAll: bool # undocumented stream: TextIO # undocumented - def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... + if sys.version_info >= (3, 12): + durations: unittest.result._DurationsType | None + def __init__(self, stream: TextIO, descriptions: bool, verbosity: int, *, durations: unittest.result._DurationsType | None = None) -> None: ... + else: + def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... def getDescription(self, test: unittest.case.TestCase) -> str: ... def printErrorList(self, flavour: str, errors: Iterable[tuple[unittest.case.TestCase, str]]) -> None: ... class TextTestRunner: resultclass: _ResultClassType - def __init__( - self, - stream: TextIO | None = None, - descriptions: bool = True, - verbosity: int = 1, - failfast: bool = False, - buffer: bool = False, - resultclass: _ResultClassType | None = None, - warnings: type[Warning] | None = None, - *, - tb_locals: bool = False, - ) -> None: ... + stream: TextIO + descriptions: bool + verbosity: int + failfast: bool + buffer: bool + warnings: type[Warning] | None + tb_locals: bool + + if sys.version_info >= (3, 12): + durations: unittest.result._DurationsType | None + def __init__( + self, + stream: TextIO | None = None, + descriptions: bool = True, + verbosity: int = 1, + failfast: bool = False, + buffer: bool = False, + resultclass: _ResultClassType | None = None, + warnings: type[Warning] | None = None, + *, + tb_locals: bool = False, + durations: unittest.result._DurationsType | None = None, + ) -> None: ... + else: + def __init__( + self, + stream: TextIO | None = None, + descriptions: bool = True, + verbosity: int = 1, + failfast: bool = False, + buffer: bool = False, + resultclass: _ResultClassType | None = None, + warnings: type[Warning] | None = None, + *, + tb_locals: bool = False, + ) -> None: ... def _makeResult(self) -> unittest.result.TestResult: ... def run(self, test: unittest.suite.TestSuite | unittest.case.TestCase) -> unittest.result.TestResult: ... diff --git a/tests/stubtest_allowlists/py312.txt b/tests/stubtest_allowlists/py312.txt index 85ce2b30101d..41c3e2b2ee22 100644 --- a/tests/stubtest_allowlists/py312.txt +++ b/tests/stubtest_allowlists/py312.txt @@ -68,17 +68,9 @@ typing_extensions.Protocol typing_extensions.SupportsAbs.__type_params__ typing_extensions.SupportsRound.__type_params__ unittest.TestLoader.loadTestsFromModule -unittest.TestProgram.__init__ -unittest.TestResult.addDuration -unittest.TextTestResult.__init__ -unittest.TextTestRunner.__init__ unittest.load_tests unittest.loader.TestLoader.loadTestsFromModule -unittest.main.TestProgram.__init__ unittest.mock.NonCallableMock.__new__ -unittest.result.TestResult.addDuration -unittest.runner.TextTestResult.__init__ -unittest.runner.TextTestRunner.__init__ urllib.request.AbstractHTTPHandler.__init__ urllib.request.HTTPSHandler.__init__ zipfile.Path.glob From b011b95e7804f43dc51e7516cc1e2e33d0bb7671 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 07:25:29 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/unittest/main.pyi | 1 + stdlib/unittest/runner.pyi | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/stdlib/unittest/main.pyi b/stdlib/unittest/main.pyi index 686bf8bc444a..d29e9a2b8da8 100644 --- a/stdlib/unittest/main.pyi +++ b/stdlib/unittest/main.pyi @@ -60,6 +60,7 @@ class TestProgram: *, tb_locals: bool = False, ) -> None: ... + def usageExit(self, msg: Any = None) -> None: ... def parseArgs(self, argv: list[str]) -> None: ... def createTests(self, from_discovery: bool = False, Loader: unittest.loader.TestLoader | None = None) -> None: ... diff --git a/stdlib/unittest/runner.pyi b/stdlib/unittest/runner.pyi index 24acd4196a9e..bbbf7d4ecd06 100644 --- a/stdlib/unittest/runner.pyi +++ b/stdlib/unittest/runner.pyi @@ -17,9 +17,12 @@ class TextTestResult(unittest.result.TestResult): stream: TextIO # undocumented if sys.version_info >= (3, 12): durations: unittest.result._DurationsType | None - def __init__(self, stream: TextIO, descriptions: bool, verbosity: int, *, durations: unittest.result._DurationsType | None = None) -> None: ... + def __init__( + self, stream: TextIO, descriptions: bool, verbosity: int, *, durations: unittest.result._DurationsType | None = None + ) -> None: ... else: def __init__(self, stream: TextIO, descriptions: bool, verbosity: int) -> None: ... + def getDescription(self, test: unittest.case.TestCase) -> str: ... def printErrorList(self, flavour: str, errors: Iterable[tuple[unittest.case.TestCase, str]]) -> None: ... @@ -61,5 +64,6 @@ class TextTestRunner: *, tb_locals: bool = False, ) -> None: ... + def _makeResult(self) -> unittest.result.TestResult: ... def run(self, test: unittest.suite.TestSuite | unittest.case.TestCase) -> unittest.result.TestResult: ... From f3f97676f662e230529c842f91307a626673f777 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 30 Aug 2023 10:27:59 +0300 Subject: [PATCH 3/7] Typo --- stdlib/unittest/result.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/unittest/result.pyi b/stdlib/unittest/result.pyi index 4ccf24d9c905..6190d419b18d 100644 --- a/stdlib/unittest/result.pyi +++ b/stdlib/unittest/result.pyi @@ -43,4 +43,4 @@ class TestResult: def addUnexpectedSuccess(self, test: unittest.case.TestCase) -> None: ... def addSubTest(self, test: unittest.case.TestCase, subtest: unittest.case.TestCase, err: OptExcInfo | None) -> None: ... if sys.version_info >= (3, 12): - def addDurations(self, test: unittest.case.TestCase, elapsed: float) -> None: ... + def addDuration(self, test: unittest.case.TestCase, elapsed: float) -> None: ... From 09bca56991687af8bc21379353b0b145759cd304 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 30 Aug 2023 11:54:11 +0300 Subject: [PATCH 4/7] Address review --- stdlib/unittest/result.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/unittest/result.pyi b/stdlib/unittest/result.pyi index 6190d419b18d..dfc505936f59 100644 --- a/stdlib/unittest/result.pyi +++ b/stdlib/unittest/result.pyi @@ -6,7 +6,7 @@ from typing import Any, TextIO, TypeVar from typing_extensions import TypeAlias _F = TypeVar("_F", bound=Callable[..., Any]) -_DurationsType: TypeAlias = list[tuple[unittest.case.TestCase, float]] +_DurationsType: TypeAlias = list[tuple[str, float]] STDOUT_LINE: str STDERR_LINE: str From 319e55566a0a1147a6f462832f7b31e7bb9015e4 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 30 Aug 2023 13:22:54 +0300 Subject: [PATCH 5/7] Address review --- stdlib/unittest/runner.pyi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stdlib/unittest/runner.pyi b/stdlib/unittest/runner.pyi index bbbf7d4ecd06..af04a78af926 100644 --- a/stdlib/unittest/runner.pyi +++ b/stdlib/unittest/runner.pyi @@ -28,12 +28,13 @@ class TextTestResult(unittest.result.TestResult): class TextTestRunner: resultclass: _ResultClassType - stream: TextIO + # TODO: add `_WritelnDecorator` type + # stream: _WritelnDecorator descriptions: bool verbosity: int failfast: bool buffer: bool - warnings: type[Warning] | None + warnings: str | None tb_locals: bool if sys.version_info >= (3, 12): @@ -46,7 +47,7 @@ class TextTestRunner: failfast: bool = False, buffer: bool = False, resultclass: _ResultClassType | None = None, - warnings: type[Warning] | None = None, + warnings: str | None = None, *, tb_locals: bool = False, durations: unittest.result._DurationsType | None = None, @@ -60,7 +61,7 @@ class TextTestRunner: failfast: bool = False, buffer: bool = False, resultclass: _ResultClassType | None = None, - warnings: type[Warning] | None = None, + warnings: str | None = None, *, tb_locals: bool = False, ) -> None: ... From b6e4128e01e32cab2113fc22fe9a3534599d91b3 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 30 Aug 2023 13:24:04 +0300 Subject: [PATCH 6/7] Address review --- stdlib/unittest/runner.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/unittest/runner.pyi b/stdlib/unittest/runner.pyi index af04a78af926..92e736a0f83e 100644 --- a/stdlib/unittest/runner.pyi +++ b/stdlib/unittest/runner.pyi @@ -5,6 +5,7 @@ import unittest.suite from collections.abc import Callable, Iterable from typing import TextIO from typing_extensions import TypeAlias +from _typeshed import Incomplete _ResultClassType: TypeAlias = Callable[[TextIO, bool, int], unittest.result.TestResult] @@ -30,6 +31,7 @@ class TextTestRunner: resultclass: _ResultClassType # TODO: add `_WritelnDecorator` type # stream: _WritelnDecorator + stream: Incomplete descriptions: bool verbosity: int failfast: bool From 395318a1c9ad419ed1d3b0cc7b9680c140bbc6e9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 30 Aug 2023 10:25:14 +0000 Subject: [PATCH 7/7] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/unittest/runner.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/unittest/runner.pyi b/stdlib/unittest/runner.pyi index 92e736a0f83e..0033083ac406 100644 --- a/stdlib/unittest/runner.pyi +++ b/stdlib/unittest/runner.pyi @@ -2,10 +2,10 @@ import sys import unittest.case import unittest.result import unittest.suite +from _typeshed import Incomplete from collections.abc import Callable, Iterable from typing import TextIO from typing_extensions import TypeAlias -from _typeshed import Incomplete _ResultClassType: TypeAlias = Callable[[TextIO, bool, int], unittest.result.TestResult]