Skip to content

Commit 8241115

Browse files
Merge python#8
8: Add warnings for strings and operations r=ltratt a=nanjekyejoannah This PR adds warnings about: - the unicode type - the `ur` literal - the incompatible `basetring type' - and mixed concat operations for strings Co-authored-by: Joannah Nanjekye <jnanjekye@python.org>
2 parents 5b876e2 + 5912c59 commit 8241115

File tree

6 files changed

+81
-1
lines changed

6 files changed

+81
-1
lines changed

Include/warnings.h

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ PyAPI_FUNC(int) PyErr_WarnExplicit_WithFix(PyObject *, const char *, const char
1616
#define PyErr_WarnPy3k(msg, stacklevel) \
1717
(Py_Py3kWarningFlag ? PyErr_WarnEx(PyExc_DeprecationWarning, msg, stacklevel) : 0)
1818

19+
#define PyErr_WarnPy3k_WithFix(msg, fix, stacklevel) \
20+
(Py_Py3kWarningFlag ? PyErr_WarnEx_WithFix(PyExc_DeprecationWarning, msg, fix, stacklevel) : 0)
21+
1922
/* DEPRECATED: Use PyErr_WarnEx() instead. */
2023
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
2124

Lib/test/string_tests.py

+18
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,24 @@ def test_mul(self):
10811081
# but either raises a MemoryError, or succeeds (if you have 54TiB)
10821082
#self.checkraises(OverflowError, 10000*'abc', '__mul__', 2000000000)
10831083

1084+
def test_py3x_warnings_isinstance(self):
1085+
with test_support.check_py3k_warnings(("the basestring type is not supported in 3.x: "
1086+
"import a third party library like six and use"
1087+
"a compatible type like string_types", Py3xWarning)):
1088+
isinstance(u"fix", basestring)
1089+
isinstance(b"fix", basestring)
1090+
isinstance("fix", basestring)
1091+
1092+
def test_py3x_warnings_join(self):
1093+
with test_support.check_py3k_warnings(("mixed bytes, str and unicode operands cannot "
1094+
"be used in string concatenation in Python 3.x: "
1095+
"convert the operand(s) so that they are the same type.", Py3xWarning)):
1096+
x = 'foo'
1097+
y = b'foo'
1098+
z = x + y
1099+
b = y + x
1100+
v = x.__add__(y)
1101+
10841102
def test_join(self):
10851103
# join now works with any sequence type
10861104
# moved here, because the argument order is

Lib/test/test_grammar.py

+21
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,27 @@ def test_paren_evaluation(self):
12291229
self.assertFalse((False is 2) is 3)
12301230
self.assertFalse(False is 2 is 3)
12311231

1232+
def test_py3x_unicode_warnings_u(self):
1233+
if sys.py3kwarning:
1234+
with warnings.catch_warnings(record=True) as w:
1235+
warnings.filterwarnings('always', category=Py3xWarning)
1236+
self.assertEqual(u'foo', u'foo')
1237+
for warning in w:
1238+
self.assertTrue(Py3xWarning is w.category)
1239+
self.assertEqual(str(w.message), "the unicode type is not supported in 3.x: " \
1240+
"use native strings for compatibility or " \
1241+
"a 'u' or 'b' prefix if a native string is not required")
1242+
1243+
def test_py3x_unicode_warnings_ur(self):
1244+
if sys.py3kwarning:
1245+
with warnings.catch_warnings(record=True) as w:
1246+
warnings.filterwarnings('always', category=Py3xWarning)
1247+
self.assertEqual(ur'foo', u'foo')
1248+
for warning in w:
1249+
self.assertTrue(Py3xWarning is w.category)
1250+
self.assertEqual(str(w.message), "the 'ur' prefix in string literals is not supported in 3.x: ",
1251+
"use a 'u' and two backslashes for a literal backslash")
1252+
12321253

12331254
def test_main():
12341255
run_unittest(TokenTests, GrammarTests)

Objects/abstract.c

+8
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,14 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
29382938
{
29392939
static PyObject *name = NULL;
29402940

2941+
if ((PyTypeObject *)cls == &PyBaseString_Type) {
2942+
if (Py_Py3kWarningFlag &&
2943+
PyErr_WarnEx_WithFix(PyExc_Py3xWarning,
2944+
"the basestring type is not supported in 3.x",
2945+
"import a third party library like six and use a compatible type like string_types", 1) < 0) {
2946+
return 0;
2947+
}
2948+
}
29412949
/* Quick test for an exact match */
29422950
if (Py_TYPE(inst) == (PyTypeObject *)cls)
29432951
return 1;

Objects/stringobject.c

+11
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,17 @@ string_concat(register PyStringObject *a, register PyObject *bb)
10291029
{
10301030
register Py_ssize_t size;
10311031
register PyStringObject *op;
1032+
if (a->ob_type != bb->ob_type) {
1033+
char msgbuf[256];
1034+
sprintf(msgbuf, "the first string is '%.200s' while the second is '%.200s': "\
1035+
"mixed bytes, str and unicode operands cannot be used in string concatenation in Python 3.x",
1036+
Py_TYPE(a)->tp_name, Py_TYPE(bb)->tp_name);
1037+
char *fix = "convert the operand(s) so that they are the same type.";
1038+
if (Py_Py3kWarningFlag &&
1039+
PyErr_WarnEx_WithFix(PyExc_Py3xWarning, msgbuf, fix, 1) < 0) {
1040+
return NULL;
1041+
}
1042+
}
10321043
if (!PyString_Check(bb)) {
10331044
#ifdef Py_USING_UNICODE
10341045
if (PyUnicode_Check(bb))

Parser/tokenizer.c

+20-1
Original file line numberDiff line numberDiff line change
@@ -1390,8 +1390,27 @@ tok_get(register struct tok_state *tok, char **p_start, char **p_end)
13901390
case 'u':
13911391
case 'U':
13921392
c = tok_nextc(tok);
1393-
if (c == 'r' || c == 'R')
1393+
if (c == 'r' || c == 'R') {
1394+
if (Py_Py3kWarningFlag) {
1395+
if (PyErr_WarnExplicit_WithFix(PyExc_Py3xWarning, "the 'ur' prefix in string literals is not supported in 3.x",
1396+
"use a 'u' and two backslashes for a literal backslash", tok->filename, tok->lineno,
1397+
NULL, NULL)) {
1398+
return NULL;
1399+
}
1400+
}
13941401
c = tok_nextc(tok);
1402+
}
1403+
else {
1404+
if (Py_Py3kWarningFlag) {
1405+
if (PyErr_WarnExplicit_WithFix(PyExc_Py3xWarning, "the unicode type is not supported in 3.x",
1406+
"use native strings for compatibility or "
1407+
"a 'u' or 'b' prefix if a native string is not required",
1408+
tok->filename, tok->lineno, NULL, NULL)) {
1409+
return NULL;
1410+
}
1411+
}
1412+
1413+
}
13951414
if (c == '"' || c == '\'')
13961415
goto letter_quote;
13971416
break;

0 commit comments

Comments
 (0)