From 49f5f8c9f5fc1adb5cebef00be1ef8f30790d847 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Tue, 24 Sep 2024 18:26:31 +0200 Subject: [PATCH 1/7] Overload Variables class for better typing experience --- .../contrib/regular_languages/compiler.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/prompt_toolkit/contrib/regular_languages/compiler.py b/src/prompt_toolkit/contrib/regular_languages/compiler.py index dd558a68a..699a600f6 100644 --- a/src/prompt_toolkit/contrib/regular_languages/compiler.py +++ b/src/prompt_toolkit/contrib/regular_languages/compiler.py @@ -42,7 +42,7 @@ from __future__ import annotations import re -from typing import Callable, Dict, Iterable, Iterator, Pattern +from typing import Callable, Dict, Iterable, Iterator, Pattern, TypeVar, overload from typing import Match as RegexMatch from .regex_parser import ( @@ -57,9 +57,7 @@ tokenize_regex, ) -__all__ = [ - "compile", -] +__all__ = ["compile", "Match", "Variables"] # Name of the named group in the regex, matching trailing input. @@ -491,6 +489,9 @@ def end_nodes(self) -> Iterable[MatchVariable]: yield MatchVariable(varname, value, (reg[0], reg[1])) +_T = TypeVar("_T") + + class Variables: def __init__(self, tuples: list[tuple[str, str, tuple[int, int]]]) -> None: #: List of (varname, value, slice) tuples. @@ -502,7 +503,13 @@ def __repr__(self) -> str: ", ".join(f"{k}={v!r}" for k, v, _ in self._tuples), ) - def get(self, key: str, default: str | None = None) -> str | None: + @overload + def get(self, key: str) -> str | None: ... + + @overload + def get(self, key: str, default: _T = None) -> str | _T: ... + + def get(self, key: str, default: _T = None) -> str | _T: items = self.getall(key) return items[0] if items else default From bb07d376f12e6fdcebced97838dee00310348eb2 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Tue, 24 Sep 2024 21:09:00 +0200 Subject: [PATCH 2/7] Fix ruff check --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index eedbdd8ef..c153c2b18 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,7 +31,7 @@ jobs: pip list - name: Ruff run: | - ruff . + ruff check . ruff format --check . typos . - name: Tests From ba7af9c2d7c1f2ce283e5d3459d1df616f08a133 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Tue, 24 Sep 2024 21:27:13 +0200 Subject: [PATCH 3/7] Fix mypy --- src/prompt_toolkit/contrib/regular_languages/compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/prompt_toolkit/contrib/regular_languages/compiler.py b/src/prompt_toolkit/contrib/regular_languages/compiler.py index 699a600f6..4009d54f2 100644 --- a/src/prompt_toolkit/contrib/regular_languages/compiler.py +++ b/src/prompt_toolkit/contrib/regular_languages/compiler.py @@ -507,9 +507,9 @@ def __repr__(self) -> str: def get(self, key: str) -> str | None: ... @overload - def get(self, key: str, default: _T = None) -> str | _T: ... + def get(self, key: str, default: str | _T) -> str | _T: ... - def get(self, key: str, default: _T = None) -> str | _T: + def get(self, key: str, default: str | _T | None = None) -> str | _T | None: items = self.getall(key) return items[0] if items else default From c9c4459b846675e68eb1ac701bfccb6827635420 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Tue, 24 Sep 2024 21:57:55 +0200 Subject: [PATCH 4/7] Fix mypy issues --- src/prompt_toolkit/output/defaults.py | 16 ++++++++-------- src/prompt_toolkit/patch_stdout.py | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/prompt_toolkit/output/defaults.py b/src/prompt_toolkit/output/defaults.py index ed114e32a..ad13a83e7 100644 --- a/src/prompt_toolkit/output/defaults.py +++ b/src/prompt_toolkit/output/defaults.py @@ -45,7 +45,7 @@ def create_output( if stdout is None: # By default, render to stdout. If the output is piped somewhere else, # render to stderr. - stdout = sys.stdout + stdout = sys.__stdout__ if always_prefer_tty: for io in [sys.stdout, sys.stderr]: @@ -54,13 +54,6 @@ def create_output( stdout = io break - # If the output is still `None`, use a DummyOutput. - # This happens for instance on Windows, when running the application under - # `pythonw.exe`. In that case, there won't be a terminal Window, and - # stdin/stdout/stderr are `None`. - if stdout is None: - return DummyOutput() - # If the patch_stdout context manager has been used, then sys.stdout is # replaced by this proxy. For prompt_toolkit applications, we want to use # the real stdout. @@ -69,6 +62,13 @@ def create_output( while isinstance(stdout, StdoutProxy): stdout = stdout.original_stdout + # If the output is still `None`, use a DummyOutput. + # This happens for instance on Windows, when running the application under + # `pythonw.exe`. In that case, there won't be a terminal Window, and + # stdin/stdout/stderr are `None`. + if stdout is None: + return DummyOutput() + if sys.platform == "win32": from .conemu import ConEmuOutput from .win32 import Win32Output diff --git a/src/prompt_toolkit/patch_stdout.py b/src/prompt_toolkit/patch_stdout.py index 4958e9d2e..454c4f03b 100644 --- a/src/prompt_toolkit/patch_stdout.py +++ b/src/prompt_toolkit/patch_stdout.py @@ -273,8 +273,8 @@ def flush(self) -> None: self._flush() @property - def original_stdout(self) -> TextIO: - return self._output.stdout or sys.__stdout__ + def original_stdout(self) -> TextIO | None: + return None # self._output.stdout or sys.__stdout__ # Attributes for compatibility with sys.__stdout__: From f43014bd48e1eeee9cfeaaf4a1386701d6edbc24 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Wed, 25 Sep 2024 10:26:22 +0200 Subject: [PATCH 5/7] Fix original_stdout function --- src/prompt_toolkit/patch_stdout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prompt_toolkit/patch_stdout.py b/src/prompt_toolkit/patch_stdout.py index 454c4f03b..e1f2a7a2c 100644 --- a/src/prompt_toolkit/patch_stdout.py +++ b/src/prompt_toolkit/patch_stdout.py @@ -274,7 +274,7 @@ def flush(self) -> None: @property def original_stdout(self) -> TextIO | None: - return None # self._output.stdout or sys.__stdout__ + return self._output.stdout or sys.__stdout__ # Attributes for compatibility with sys.__stdout__: From ad1a312b696fa42c91a8c7d1940ca29e7198d1e7 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Wed, 25 Sep 2024 11:33:11 +0200 Subject: [PATCH 6/7] Update `create_output` signature --- src/prompt_toolkit/output/defaults.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/prompt_toolkit/output/defaults.py b/src/prompt_toolkit/output/defaults.py index ad13a83e7..431cbe717 100644 --- a/src/prompt_toolkit/output/defaults.py +++ b/src/prompt_toolkit/output/defaults.py @@ -1,7 +1,7 @@ from __future__ import annotations import sys -from typing import TextIO, cast +from typing import TYPE_CHECKING, TextIO, cast from prompt_toolkit.utils import ( get_bell_environment_variable, @@ -13,13 +13,17 @@ from .color_depth import ColorDepth from .plain_text import PlainTextOutput +if TYPE_CHECKING: + from prompt_toolkit.patch_stdout import StdoutProxy + + __all__ = [ "create_output", ] def create_output( - stdout: TextIO | None = None, always_prefer_tty: bool = False + stdout: TextIO | StdoutProxy | None = None, always_prefer_tty: bool = False ) -> Output: """ Return an :class:`~prompt_toolkit.output.Output` instance for the command @@ -45,7 +49,7 @@ def create_output( if stdout is None: # By default, render to stdout. If the output is piped somewhere else, # render to stderr. - stdout = sys.__stdout__ + stdout = sys.stdout if always_prefer_tty: for io in [sys.stdout, sys.stderr]: @@ -57,8 +61,6 @@ def create_output( # If the patch_stdout context manager has been used, then sys.stdout is # replaced by this proxy. For prompt_toolkit applications, we want to use # the real stdout. - from prompt_toolkit.patch_stdout import StdoutProxy - while isinstance(stdout, StdoutProxy): stdout = stdout.original_stdout From 189a8b7a338ccd997be6f7ed418bdf401b2942c9 Mon Sep 17 00:00:00 2001 From: Tomasz Chalupnik Date: Wed, 25 Sep 2024 11:38:26 +0200 Subject: [PATCH 7/7] Update `create_output` signature --- src/prompt_toolkit/output/defaults.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/prompt_toolkit/output/defaults.py b/src/prompt_toolkit/output/defaults.py index 431cbe717..6b06ed43c 100644 --- a/src/prompt_toolkit/output/defaults.py +++ b/src/prompt_toolkit/output/defaults.py @@ -61,6 +61,8 @@ def create_output( # If the patch_stdout context manager has been used, then sys.stdout is # replaced by this proxy. For prompt_toolkit applications, we want to use # the real stdout. + from prompt_toolkit.patch_stdout import StdoutProxy + while isinstance(stdout, StdoutProxy): stdout = stdout.original_stdout