diff options
author | Sanyam Khurana <sanyam@sanyamkhurana.com> | 2017-08-18 10:37:36 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-08-18 10:37:36 (GMT) |
commit | 5e2eb35bbed3e84079165e576cdb50ef36e13493 (patch) | |
tree | a2f513631279ac12788b04a56f7f61fb63c81068 | |
parent | ad7eaed54382b346784e51a6f0122ce81e8842b5 (diff) | |
download | cpython-5e2eb35bbed3e84079165e576cdb50ef36e13493.zip cpython-5e2eb35bbed3e84079165e576cdb50ef36e13493.tar.gz cpython-5e2eb35bbed3e84079165e576cdb50ef36e13493.tar.bz2 |
bpo-30721: Show correct syntax hint in Py3 when using Py2 redirection syntax (#2345)
-rw-r--r-- | Lib/test/test_print.py | 33 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2017-08-18-15-15-20.bpo-30721.Hmc56z.rst | 2 | ||||
-rw-r--r-- | Objects/abstract.c | 15 |
3 files changed, 50 insertions, 0 deletions
diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index 03f13b4..8099327 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(<message>, ' + 'file=<output_stream>)', 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(<message>, ' + 'file=<output_stream>)', 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 0000000..da553d6 --- /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 cb026c0..abd9795 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(<message>, " + "file=<output_stream>)\"", + op_name, + v->ob_type->tp_name, + w->ob_type->tp_name); + return NULL; + } + return binop_type_error(v, w, op_name); } return result; |