mirror of https://github.com/python/cpython.git
[3.13] gh-130999: Avoid exiting the new REPL when there are non-string candidates for suggestions (gh-131001) (gh-135020)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
parent
11f7270e8f
commit
7ca17edd13
|
@ -1342,6 +1342,17 @@ def test_null_byte(self):
|
|||
self.assertEqual(exit_code, 0)
|
||||
self.assertNotIn("TypeError", output)
|
||||
|
||||
@force_not_colorized
|
||||
def test_non_string_suggestion_candidates(self):
|
||||
commands = ("import runpy\n"
|
||||
"runpy._run_module_code('blech', {0: '', 'bluch': ''}, '')\n"
|
||||
"exit()\n")
|
||||
|
||||
output, exit_code = self.run_repl(commands)
|
||||
self.assertEqual(exit_code, 0)
|
||||
self.assertNotIn("all elements in 'candidates' must be strings", output)
|
||||
self.assertIn("bluch", output)
|
||||
|
||||
def test_readline_history_file(self):
|
||||
# skip, if readline module is not available
|
||||
readline = import_module('readline')
|
||||
|
|
|
@ -4176,6 +4176,15 @@ def __dir__(self):
|
|||
self.assertNotIn("blech", actual)
|
||||
self.assertNotIn("oh no!", actual)
|
||||
|
||||
def test_attribute_error_with_non_string_candidates(self):
|
||||
class T:
|
||||
bluch = 1
|
||||
|
||||
instance = T()
|
||||
instance.__dict__[0] = 1
|
||||
actual = self.get_suggestion(instance, 'blich')
|
||||
self.assertIn("bluch", actual)
|
||||
|
||||
def test_attribute_error_with_bad_name(self):
|
||||
def raise_attribute_error_with_bad_name():
|
||||
raise AttributeError(name=12, obj=23)
|
||||
|
@ -4211,8 +4220,8 @@ def make_module(self, code):
|
|||
|
||||
return mod_name
|
||||
|
||||
def get_import_from_suggestion(self, mod_dict, name):
|
||||
modname = self.make_module(mod_dict)
|
||||
def get_import_from_suggestion(self, code, name):
|
||||
modname = self.make_module(code)
|
||||
|
||||
def callable():
|
||||
try:
|
||||
|
@ -4289,6 +4298,13 @@ def test_import_from_suggestions_underscored(self):
|
|||
self.assertIn("'_bluch'", self.get_import_from_suggestion(code, '_luch'))
|
||||
self.assertNotIn("'_bluch'", self.get_import_from_suggestion(code, 'bluch'))
|
||||
|
||||
def test_import_from_suggestions_non_string(self):
|
||||
modWithNonStringAttr = textwrap.dedent("""\
|
||||
globals()[0] = 1
|
||||
bluch = 1
|
||||
""")
|
||||
self.assertIn("'bluch'", self.get_import_from_suggestion(modWithNonStringAttr, 'blech'))
|
||||
|
||||
def test_import_from_suggestions_do_not_trigger_for_long_attributes(self):
|
||||
code = "blech = None"
|
||||
|
||||
|
@ -4385,6 +4401,15 @@ def func():
|
|||
actual = self.get_suggestion(func)
|
||||
self.assertIn("'ZeroDivisionError'?", actual)
|
||||
|
||||
def test_name_error_suggestions_with_non_string_candidates(self):
|
||||
def func():
|
||||
abc = 1
|
||||
custom_globals = globals().copy()
|
||||
custom_globals[0] = 1
|
||||
print(eval("abv", custom_globals, locals()))
|
||||
actual = self.get_suggestion(func)
|
||||
self.assertIn("abc", actual)
|
||||
|
||||
def test_name_error_suggestions_do_not_trigger_for_long_names(self):
|
||||
def func():
|
||||
somethingverywronghehehehehehe = None
|
||||
|
|
|
@ -1490,7 +1490,11 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
|
|||
if isinstance(exc_value, AttributeError):
|
||||
obj = exc_value.obj
|
||||
try:
|
||||
d = dir(obj)
|
||||
try:
|
||||
d = dir(obj)
|
||||
except TypeError: # Attributes are unsortable, e.g. int and str
|
||||
d = list(obj.__class__.__dict__.keys()) + list(obj.__dict__.keys())
|
||||
d = sorted([x for x in d if isinstance(x, str)])
|
||||
hide_underscored = (wrong_name[:1] != '_')
|
||||
if hide_underscored and tb is not None:
|
||||
while tb.tb_next is not None:
|
||||
|
@ -1505,7 +1509,11 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
|
|||
elif isinstance(exc_value, ImportError):
|
||||
try:
|
||||
mod = __import__(exc_value.name)
|
||||
d = dir(mod)
|
||||
try:
|
||||
d = dir(mod)
|
||||
except TypeError: # Attributes are unsortable, e.g. int and str
|
||||
d = list(mod.__dict__.keys())
|
||||
d = sorted([x for x in d if isinstance(x, str)])
|
||||
if wrong_name[:1] != '_':
|
||||
d = [x for x in d if x[:1] != '_']
|
||||
except Exception:
|
||||
|
@ -1523,6 +1531,7 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
|
|||
+ list(frame.f_globals)
|
||||
+ list(frame.f_builtins)
|
||||
)
|
||||
d = [x for x in d if isinstance(x, str)]
|
||||
|
||||
# Check first if we are in a method and the instance
|
||||
# has the wrong name as attribute
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Avoid exiting the new REPL and offer suggestions even if there are non-string
|
||||
candidates when errors occur.
|
Loading…
Reference in New Issue