From d1cdda5f5dc485ee60ee59bb2e792787f6ce21bc Mon Sep 17 00:00:00 2001 From: 00ll00 Date: Fri, 29 Aug 2025 11:43:52 +0000 Subject: [PATCH 1/7] add "type" to soft keyword check --- Lib/_pyrepl/utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index fd788c8429e15b..dfd79c876b93f6 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -257,6 +257,14 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: return True case (TI(string="case"), TI(string="_"), TI(string=":")): return True + case ( + None | TI(T.NEWLINE) | TI(T.INDENT) | TI(string=":"), + TI(string="type"), + TI(T.NAME, string=s) + ): + if keyword.iskeyword(s): + return False + return True case _: return False From 64a443b9c43a056ffc8a1e5067c69f67ebc92d9c Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:56:56 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst diff --git a/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst b/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst new file mode 100644 index 00000000000000..192fcb1b143dfc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst @@ -0,0 +1 @@ +The REPL now highlights "type" as a soft keyword in type statements. From 16e6f75af4673d6badbe242eff9e782bbcd592ba Mon Sep 17 00:00:00 2001 From: 00ll00 <40747228+00ll00@users.noreply.github.com> Date: Fri, 29 Aug 2025 21:25:55 +0800 Subject: [PATCH 3/7] Update Lib/_pyrepl/utils.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/_pyrepl/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index dfd79c876b93f6..e8e6657d52227f 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -262,9 +262,7 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: TI(string="type"), TI(T.NAME, string=s) ): - if keyword.iskeyword(s): - return False - return True + return not keyword.iskeyword(s): case _: return False From 23fbfe497495f736a5877b2091a6022fe1140aab Mon Sep 17 00:00:00 2001 From: 00ll00 <40747228+00ll00@users.noreply.github.com> Date: Fri, 29 Aug 2025 21:26:08 +0800 Subject: [PATCH 4/7] Update Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst b/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst index 192fcb1b143dfc..9e0218e02664c6 100644 --- a/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst +++ b/Misc/NEWS.d/next/Library/2025-08-29-12-56-55.gh-issue-138239.uthZFI.rst @@ -1 +1,2 @@ -The REPL now highlights "type" as a soft keyword in type statements. +The REPL now highlights :keyword:`type` as a soft keyword +in :ref:`type statements `. From 948a0b0a26a58501b9c31dd5637b8be94110eb1c Mon Sep 17 00:00:00 2001 From: 00ll00 Date: Fri, 29 Aug 2025 13:33:38 +0000 Subject: [PATCH 5/7] * --- Lib/_pyrepl/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index e8e6657d52227f..05487546cf5d7e 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -262,7 +262,7 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: TI(string="type"), TI(T.NAME, string=s) ): - return not keyword.iskeyword(s): + return not keyword.iskeyword(s) case _: return False From eb3f8bcaa19cd415a1e2c41b186d6a666f1a3f2e Mon Sep 17 00:00:00 2001 From: 00ll00 Date: Mon, 1 Sep 2025 12:27:54 +0000 Subject: [PATCH 6/7] fix type statement highlight after DEDENT --- Lib/_pyrepl/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index 05487546cf5d7e..6467b43557814d 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -258,7 +258,7 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: case (TI(string="case"), TI(string="_"), TI(string=":")): return True case ( - None | TI(T.NEWLINE) | TI(T.INDENT) | TI(string=":"), + None | TI(T.NEWLINE) | TI(T.INDENT) | TI(T.DEDENT) | TI(string=":"), TI(string="type"), TI(T.NAME, string=s) ): From 131a08fa8cebad09579995112b9b264b2cec709d Mon Sep 17 00:00:00 2001 From: 00ll00 Date: Mon, 1 Sep 2025 12:32:22 +0000 Subject: [PATCH 7/7] add tests for type statement highlighting --- Lib/test/test_pyrepl/test_reader.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index 9a02dff7387563..b1b6ae16a1e592 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -378,6 +378,7 @@ def funct(case: str = sys.platform) -> None: case "ios" | "android": print("on the phone") case _: print('arms around', match.group(1)) + type type = type[type] """ ) expected = dedent( @@ -397,6 +398,7 @@ def funct(case: str = sys.platform) -> None: {K}case{z} {s}"ios"{z} {o}|{z} {s}"android"{z}{o}:{z} {b}print{z}{o}({z}{s}"on the phone"{z}{o}){z} {K}case{z} {K}_{z}{o}:{z} {b}print{z}{o}({z}{s}'arms around'{z}{o},{z} match{o}.{z}group{o}({z}{n}1{z}{o}){z}{o}){z} + {K}type{z} {b}type{z} {o}={z} {b}type{z}{o}[{z}{b}type{z}{o}]{z} """ ) expected_sync = expected.format(a="", **colors) @@ -404,14 +406,14 @@ def funct(case: str = sys.platform) -> None: reader, _ = handle_all_events(events) self.assert_screen_equal(reader, code, clean=True) self.assert_screen_equal(reader, expected_sync) - self.assertEqual(reader.pos, 396) - self.assertEqual(reader.cxy, (0, 15)) + self.assertEqual(reader.pos, 419) + self.assertEqual(reader.cxy, (0, 16)) async_msg = "{k}async{z} ".format(**colors) expected_async = expected.format(a=async_msg, **colors) more_events = itertools.chain( code_to_events(code), - [Event(evt="key", data="up", raw=bytearray(b"\x1bOA"))] * 14, + [Event(evt="key", data="up", raw=bytearray(b"\x1bOA"))] * 15, code_to_events("async "), ) reader, _ = handle_all_events(more_events)