diff options
| author | Pablo Galindo <Pablogsal@gmail.com> | 2021-04-14 15:10:33 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-04-14 15:10:33 +0100 |
| commit | 5bf8bf2267cd109970b2d946d43b2e9f71379ba2 (patch) | |
| tree | a29b493cace0ba9cf1d5af516750ff9348ce6c49 /Lib/test/test_exceptions.py | |
| parent | c4073a24f95b54705416138dc1f20141ad76dd37 (diff) | |
| download | cpython-git-5bf8bf2267cd109970b2d946d43b2e9f71379ba2.tar.gz | |
bpo-38530: Offer suggestions on NameError (GH-25397)
When printing NameError raised by the interpreter, PyErr_Display
will offer suggestions of simmilar variable names in the function that the exception
was raised from:
>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?
Diffstat (limited to 'Lib/test/test_exceptions.py')
| -rw-r--r-- | Lib/test/test_exceptions.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index e1a5ec76d7..4f3c9ab456 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1413,6 +1413,129 @@ class ExceptionTests(unittest.TestCase): gc_collect() +global_for_suggestions = None + +class NameErrorTests(unittest.TestCase): + def test_name_error_has_name(self): + try: + bluch + except NameError as exc: + self.assertEqual("bluch", exc.name) + + def test_name_error_suggestions(self): + def Substitution(): + noise = more_noise = a = bc = None + blech = None + print(bluch) + + def Elimination(): + noise = more_noise = a = bc = None + blch = None + print(bluch) + + def Addition(): + noise = more_noise = a = bc = None + bluchin = None + print(bluch) + + def SubstitutionOverElimination(): + blach = None + bluc = None + print(bluch) + + def SubstitutionOverAddition(): + blach = None + bluchi = None + print(bluch) + + def EliminationOverAddition(): + blucha = None + bluc = None + print(bluch) + + for func, suggestion in [(Substitution, "blech?"), + (Elimination, "blch?"), + (Addition, "bluchin?"), + (EliminationOverAddition, "blucha?"), + (SubstitutionOverElimination, "blach?"), + (SubstitutionOverAddition, "blach?")]: + err = None + try: + func() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + self.assertIn(suggestion, err.getvalue()) + + def test_name_error_suggestions_from_globals(self): + def func(): + print(global_for_suggestio) + try: + func() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + self.assertIn("global_for_suggestions?", err.getvalue()) + + def test_name_error_suggestions_do_not_trigger_for_long_names(self): + def f(): + somethingverywronghehehehehehe = None + print(somethingverywronghe) + + try: + f() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("somethingverywronghehe", err.getvalue()) + + def test_name_error_suggestions_do_not_trigger_for_big_dicts(self): + def f(): + # Mutating locals() is unreliable, so we need to do it by hand + a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = a10 = a11 = a12 = a13 = \ + a14 = a15 = a16 = a17 = a18 = a19 = a20 = a21 = a22 = a23 = a24 = a25 = \ + a26 = a27 = a28 = a29 = a30 = a31 = a32 = a33 = a34 = a35 = a36 = a37 = \ + a38 = a39 = a40 = a41 = a42 = a43 = a44 = a45 = a46 = a47 = a48 = a49 = \ + a50 = a51 = a52 = a53 = a54 = a55 = a56 = a57 = a58 = a59 = a60 = a61 = \ + a62 = a63 = a64 = a65 = a66 = a67 = a68 = a69 = a70 = a71 = a72 = a73 = \ + a74 = a75 = a76 = a77 = a78 = a79 = a80 = a81 = a82 = a83 = a84 = a85 = \ + a86 = a87 = a88 = a89 = a90 = a91 = a92 = a93 = a94 = a95 = a96 = a97 = \ + a98 = a99 = a100 = a101 = a102 = a103 = None + print(a0) + + try: + f() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("a10", err.getvalue()) + + def test_name_error_with_custom_exceptions(self): + def f(): + blech = None + raise NameError() + + try: + f() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("blech", err.getvalue()) + + def f(): + blech = None + raise NameError + + try: + f() + except NameError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("blech", err.getvalue()) class AttributeErrorTests(unittest.TestCase): def test_attributes(self): |
