diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_repr_utils.py b/python/helpers/pydev/_pydevd_bundle/pydevd_repr_utils.py index 15331f7b7be5..c7ba7e796ab9 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_repr_utils.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_repr_utils.py @@ -166,10 +166,15 @@ if IS_PY3K: if result is not None: return result - # if `__str__` method is overridden then return str(x) - if x.__str__ != object.__str__: + # if `__repr__` is overridden, then use `reprlib` + if x.__class__.__repr__ != object.__repr__: + return super().repr_instance(x, level) + + # if `__str__` is overridden, then return str(x) + if x.__class__.__str__ != object.__str__: return str(x) + # else use `reprlib` return super().repr_instance(x, level) @@ -188,7 +193,11 @@ else: return ('%s' % take_first_n_coll_elements(value, MAX_REPR_ITEM_SIZE)).rstrip(')]}') + '...' return None - # other types + # if `__repr__` is overridden, then return repr(value) + if hasattr(value.__class__, "__repr__"): + return repr(value) + + # else return str(value) diff --git a/python/testData/debug/test_string_representation_in_variables_view.py b/python/testData/debug/test_string_representation_in_variables_view.py new file mode 100644 index 000000000000..00560551b150 --- /dev/null +++ b/python/testData/debug/test_string_representation_in_variables_view.py @@ -0,0 +1,18 @@ +class FooStr: + def __str__(self): + return "str" + + +class FooRepr: + def __repr__(self): + return "repr" + + +class FooReprlib: + pass + + +foo_str = FooStr() +foo_repr = FooRepr() +foo_reprlib = FooReprlib() +print() diff --git a/python/testSrc/com/jetbrains/env/debug/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/debug/PythonDebuggerTest.java index 7995dd6c5759..dd63bdf26e6e 100644 --- a/python/testSrc/com/jetbrains/env/debug/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/debug/PythonDebuggerTest.java @@ -15,6 +15,7 @@ import com.jetbrains.env.EnvTestTagsRequired; import com.jetbrains.env.PyEnvTestCase; import com.jetbrains.python.console.pydev.PydevCompletionVariant; import com.jetbrains.python.debugger.PyDebugValue; +import com.jetbrains.python.debugger.PyDebuggerException; import com.jetbrains.python.debugger.PyExceptionBreakpointProperties; import com.jetbrains.python.debugger.PyExceptionBreakpointType; import com.jetbrains.python.debugger.pydev.ProcessDebugger; @@ -1709,6 +1710,34 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + @Test + public void testStringRepresentationInVariablesView() { + runPythonTest(new PyDebuggerTask("/debug", "test_string_representation_in_variables_view.py") { + @Override + public void before() { + toggleBreakpoint(getFilePath(getScriptName()), 17); + } + + @Override + public void testing() throws Exception { + waitForPause(); + List frameVariables = loadFrame(); + checkVariableValue(frameVariables, "str", "foo_str"); + checkVariableValue(frameVariables, "repr", "foo_repr"); + String expected = eval("repr(foo_reprlib)").getValue().replaceAll("[\"']", ""); + checkVariableValue(frameVariables, expected, "foo_reprlib"); + resume(); + waitForTerminate(); + } + + private void checkVariableValue(List frameVariables, String expected, String name) throws PyDebuggerException { + PyDebugValue value = findDebugValueByName(frameVariables, name); + loadVariable(value); + assertEquals(expected, value.getValue()); + } + }); + } + private static class PyDebuggerTaskTagAware extends PyDebuggerTask { private PyDebuggerTaskTagAware(@Nullable String relativeTestDataPath, String scriptName) {