From 5e2eb35bbed3e84079165e576cdb50ef36e13493 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Fri, 18 Aug 2017 16:07:36 +0530 Subject: [PATCH] bpo-30721: Show correct syntax hint in Py3 when using Py2 redirection syntax (#2345) --- Lib/test/test_print.py | 33 +++++++++++++++++++ .../2017-08-18-15-15-20.bpo-30721.Hmc56z.rst | 2 ++ Objects/abstract.c | 15 +++++++++ 3 files changed, 50 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-08-18-15-15-20.bpo-30721.Hmc56z.rst diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index 03f13b4edf..80993279b8 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -1,4 +1,5 @@ import unittest +import sys from io import StringIO from test import support @@ -155,6 +156,38 @@ class TestPy2MigrationHint(unittest.TestCase): self.assertIn('print("Hello World", end=" ")', str(context.exception)) + def test_stream_redirection_hint_for_py2_migration(self): + # Test correct hint produced for Py2 redirection syntax + with self.assertRaises(TypeError) as context: + print >> sys.stderr, "message" + self.assertIn('Did you mean "print(, ' + 'file=)', str(context.exception)) + + # Test correct hint is produced in the case where RHS implements + # __rrshift__ but returns NotImplemented + with self.assertRaises(TypeError) as context: + print >> 42 + self.assertIn('Did you mean "print(, ' + 'file=)', str(context.exception)) + + # Test stream redirection hint is specific to print + with self.assertRaises(TypeError) as context: + max >> sys.stderr + self.assertNotIn('Did you mean ', str(context.exception)) + + # Test stream redirection hint is specific to rshift + with self.assertRaises(TypeError) as context: + print << sys.stderr + self.assertNotIn('Did you mean', str(context.exception)) + + # Ensure right operand implementing rrshift still works + class OverrideRRShift: + def __rrshift__(self, lhs): + return 42 # Force result independent of LHS + + self.assertEqual(print >> OverrideRRShift(), 42) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-08-18-15-15-20.bpo-30721.Hmc56z.rst b/Misc/NEWS.d/next/Core and Builtins/2017-08-18-15-15-20.bpo-30721.Hmc56z.rst new file mode 100644 index 0000000000..da553d654e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-08-18-15-15-20.bpo-30721.Hmc56z.rst @@ -0,0 +1,2 @@ +``print`` now shows correct usage hint for using Python 2 redirection +syntax. Patch by Sanyam Khurana. diff --git a/Objects/abstract.c b/Objects/abstract.c index cb026c0df5..abd97953bd 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -819,6 +819,21 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name) PyObject *result = binary_op1(v, w, op_slot); if (result == Py_NotImplemented) { Py_DECREF(result); + + if (op_slot == NB_SLOT(nb_rshift) && + PyCFunction_Check(v) && + strcmp(((PyCFunctionObject *)v)->m_ml->ml_name, "print") == 0) + { + PyErr_Format(PyExc_TypeError, + "unsupported operand type(s) for %.100s: " + "'%.100s' and '%.100s'. Did you mean \"print(, " + "file=)\"", + op_name, + v->ob_type->tp_name, + w->ob_type->tp_name); + return NULL; + } + return binop_type_error(v, w, op_name); } return result; -- 2.40.0