From 817cd5cb464dddd4f9d5bf84e2dc69f540e0182f Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 19:16:20 +0530 Subject: [PATCH 01/15] Fix crashing pyrepl when NameError occurres in __getattr__ method --- Lib/test/test_traceback.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index d5b00a3bb628cb..4bbdb28e7728e3 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5086,6 +5086,16 @@ def baz(self): self.assertNotIn('self.', suggestion) self.assertIn("'spam'", suggestion) + def test_unbound_local_error_with_getattr(self): + class A: + def __getattr__(self, x): + print(x) + print(qq) + instance = A() + actual = self.get_suggestion(instance, "pop") + self.assertIn("NameError: name 'qq' is not defined", actual) + self.assertEqual(actual.count("NameError: name 'qq' is not defined"), 1) + def test_unbound_local_error_does_not_match(self): def func(): something = 3 From 273de1f649c6b4c94b19e5d3bae700c12340fa01 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 19:56:20 +0530 Subject: [PATCH 02/15] Fix test failures --- Lib/test/test_traceback.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 4bbdb28e7728e3..bf9fd4e2ba4462 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5093,8 +5093,8 @@ def __getattr__(self, x): print(qq) instance = A() actual = self.get_suggestion(instance, "pop") - self.assertIn("NameError: name 'qq' is not defined", actual) - self.assertEqual(actual.count("NameError: name 'qq' is not defined"), 1) + self.assertRegex(actual, r"NameError:.* name 'qq' is not defined") + self.assertEqual(actual.count("NameError"), 1) def test_unbound_local_error_does_not_match(self): def func(): From f77736cca15d4ff2551c9a848434b9f111ff0343 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 20:00:19 +0530 Subject: [PATCH 03/15] Update the test name --- Lib/test/test_traceback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index bf9fd4e2ba4462..fbecd94849180b 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5086,7 +5086,7 @@ def baz(self): self.assertNotIn('self.', suggestion) self.assertIn("'spam'", suggestion) - def test_unbound_local_error_with_getattr(self): + def test_name_error_with_getattr(self): class A: def __getattr__(self, x): print(x) From 1d640c2b7da6014f51a2c47ce313aa0a9f36fb3a Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 20:09:29 +0530 Subject: [PATCH 04/15] Fix test failure --- Lib/test/test_traceback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index fbecd94849180b..4eb48f45b4b34c 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5093,7 +5093,7 @@ def __getattr__(self, x): print(qq) instance = A() actual = self.get_suggestion(instance, "pop") - self.assertRegex(actual, r"NameError:.* name 'qq' is not defined") + self.assertRegex(actual, r"NameError.*:.* name 'qq' is not defined") self.assertEqual(actual.count("NameError"), 1) def test_unbound_local_error_does_not_match(self): From bbb1d26f9c802fe074660050283d71214c23941c Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 20:20:35 +0530 Subject: [PATCH 05/15] Make the check simple --- Lib/test/test_traceback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 4eb48f45b4b34c..f68281831f52f9 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5093,7 +5093,7 @@ def __getattr__(self, x): print(qq) instance = A() actual = self.get_suggestion(instance, "pop") - self.assertRegex(actual, r"NameError.*:.* name 'qq' is not defined") + self.assertIn("name 'qq' is not defined", actual) self.assertEqual(actual.count("NameError"), 1) def test_unbound_local_error_does_not_match(self): From d57f81573ecba1ccd9d0b6df7bd062725733bf6e Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:39:36 +0000 Subject: [PATCH 06/15] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst new file mode 100644 index 00000000000000..a1d91a59058481 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -0,0 +1 @@ +Fix crashing pyrepl when `NameError` occurres in `__getattr__` method From a4a7b43d683cdd5ab2910a50dcff6ab801b7bb73 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Mon, 3 Feb 2025 22:14:18 +0530 Subject: [PATCH 07/15] Update NEWS.d description --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index a1d91a59058481..a0bd9f9cbf2d10 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix crashing pyrepl when `NameError` occurres in `__getattr__` method +Fix pyrepl crash when a :func:`NameError` occurs in the :meth:`__getattr__` method From 3384adc1f7fdcf3151a7f1e295c8c4bb63fc86de Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 4 Feb 2025 11:49:03 +0530 Subject: [PATCH 08/15] Update patch --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index a0bd9f9cbf2d10..4c3cd299ef0a7a 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix pyrepl crash when a :func:`NameError` occurs in the :meth:`__getattr__` method +Fix pyrepl crash when a :exc:`NameError` occurs in the `__getattr__` method. From b6ae827b477df9eb327a8433deda7d5495850328 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 4 Feb 2025 11:51:57 +0530 Subject: [PATCH 09/15] Fix Lint failure: --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index 4c3cd299ef0a7a..652d01d8681379 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix pyrepl crash when a :exc:`NameError` occurs in the `__getattr__` method. +Fix pyrepl crash when a :exc:`NameError` occurs in the ``__getattr__`` method. From 121e7e9ddc92f6088a6f87aafa57fd9c2a40ce3c Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Tue, 4 Feb 2025 15:27:32 +0530 Subject: [PATCH 10/15] Address review comments --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index 652d01d8681379..8b1f77141fd3b6 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix pyrepl crash when a :exc:`NameError` occurs in the ``__getattr__`` method. +Fix pyrepl crash when a :exc:`NameError` occurs in the :meth:`~object.__getattr__` method. From f9b300211262a1dec4e6f0df2169db5db303b690 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 5 Feb 2025 15:06:29 +0530 Subject: [PATCH 11/15] Handle __getattribute__ case as well --- Lib/test/test_traceback.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index f68281831f52f9..c6bd464af78068 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5091,10 +5091,16 @@ class A: def __getattr__(self, x): print(x) print(qq) - instance = A() - actual = self.get_suggestion(instance, "pop") - self.assertIn("name 'qq' is not defined", actual) - self.assertEqual(actual.count("NameError"), 1) + class B: + def __getattribute__(self, x): + print(x) + print(qq) + + for name, instance in (("a", A()), ("b", B())): + with self.subTest(name=name): + actual = self.get_suggestion(instance, "pop") + self.assertIn("name 'qq' is not defined", actual) + self.assertEqual(actual.count("NameError"), 1) def test_unbound_local_error_does_not_match(self): def func(): From 8e392b94a2cdb0da5261deb01cc0ad731f6503d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Wed, 5 Feb 2025 15:20:20 +0530 Subject: [PATCH 12/15] Update 2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index 8b1f77141fd3b6..a3f41a8a629916 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix pyrepl crash when a :exc:`NameError` occurs in the :meth:`~object.__getattr__` method. +Fix pyrepl crash when a :exc:`NameError` occurs in the :meth:`~object.__getattr__`, and :meth:`~object.__getattribute__` method. From 11cc8ddfef1d55ef93b44cc012e15826195b88ad Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 5 Feb 2025 16:11:03 +0530 Subject: [PATCH 13/15] Add another test for NameError for property function, and also wrap exception around hasattr block --- Lib/test/test_traceback.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index c6bd464af78068..d9b88767c5e813 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5102,6 +5102,16 @@ def __getattribute__(self, x): self.assertIn("name 'qq' is not defined", actual) self.assertEqual(actual.count("NameError"), 1) + def test_name_error_with_property_name(self): + class A: + @property + def past(self): + past + instance = A() + actual = self.get_suggestion(instance, "past") + self.assertIn("name 'past' is not defined", actual) + self.assertEqual(actual.count("NameError"), 1) + def test_unbound_local_error_does_not_match(self): def func(): something = 3 From 2580ec009f7ef2e74288d7ca071d20646058cb30 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 5 Feb 2025 16:14:16 +0530 Subject: [PATCH 14/15] Update the description --- .../next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst index a3f41a8a629916..f049abb89a1374 100644 --- a/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst +++ b/Misc/NEWS.d/next/Library/2025-02-03-16-39-35.gh-issue-129605.sN_0uq.rst @@ -1 +1 @@ -Fix pyrepl crash when a :exc:`NameError` occurs in the :meth:`~object.__getattr__`, and :meth:`~object.__getattribute__` method. +Fix pyrepl crash when a :exc:`NameError` occurs in the :meth:`~object.__getattr__`, :meth:`~object.__getattribute__` and any method of a class. From f15fe132f613ceca61843ebf24371f41059dd02d Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 5 Feb 2025 16:40:00 +0530 Subject: [PATCH 15/15] Address review comments --- Lib/test/test_traceback.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index d9b88767c5e813..cf1e28e68a0e40 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -5096,8 +5096,8 @@ def __getattribute__(self, x): print(x) print(qq) - for name, instance in (("a", A()), ("b", B())): - with self.subTest(name=name): + for instance in (A(), B()): + with self.subTest(instance=instance): actual = self.get_suggestion(instance, "pop") self.assertIn("name 'qq' is not defined", actual) self.assertEqual(actual.count("NameError"), 1)