[3.6] bpo-31232: Backport custom print rshift message (GH-3155)
bpo-30721 added a "Did you mean ...?" suggestion to rshift TypeError messages that triggers when the LHS is a Python C function called "print". Since this custom error message is expected to be triggered primarily by attempts to use Python 2 print redirection syntax in Python 3, and is incredibly unlikely to be encountered otherwise, it is also being backported to the next 3.6 maintenance release. Initial patch by Sanyam Khurana.
This commit is contained in:
parent
b50e7683ac
commit
1a05e87ec7
|
@ -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()
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
``print`` now shows correct usage hint for using Python 2 redirection
|
||||
syntax. Patch by Sanyam Khurana.
|
|
@ -809,6 +809,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;
|
||||
|
|
Loading…
Reference in New Issue