diff -r d478a2a5738a Doc/using/cmdline.rst --- a/Doc/using/cmdline.rst Fri Mar 20 10:37:34 2015 +0100 +++ b/Doc/using/cmdline.rst Fri Mar 20 12:07:07 2015 +0200 @@ -190,9 +190,12 @@ Miscellaneous options .. cmdoption:: -b - Issue a warning when comparing str and bytes. Issue an error when the + Issue a warning when comparing :class:`bytes` or :class:`bytearray` with + :class:`str` or :class:`bytes` with :class:`int`. Issue an error when the option is given twice (:option:`-bb`). + .. versionchanged: 3.5 + Affects comparisons of :class:`bytes` with :class:`int`. .. cmdoption:: -B diff -r d478a2a5738a Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst Fri Mar 20 10:37:34 2015 +0100 +++ b/Doc/whatsnew/3.5.rst Fri Mar 20 12:07:07 2015 +0200 @@ -162,6 +162,8 @@ Some smaller changes made to the core Py error handlers now works with decoding and translating. (Contributed by Serhiy Storchaka in :issue:`19676` and :issue:`22286`.) +* The :option:`-b` option now affects comparisons of :class:`bytes` with + :class:`int`. (Contributed by Serhiy Storchaka in :issue:`23681`) New Modules diff -r d478a2a5738a Lib/poplib.py --- a/Lib/poplib.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/poplib.py Fri Mar 20 12:07:07 2015 +0200 @@ -136,7 +136,7 @@ class POP3: # so only possibilities are ...LF, ...CRLF, CR...LF if line[-2:] == CRLF: return line[:-2], octets - if line[0] == CR: + if line[:1] == CR: return line[1:-1], octets return line[:-1], octets diff -r d478a2a5738a Lib/quopri.py --- a/Lib/quopri.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/quopri.py Fri Mar 20 12:07:07 2015 +0200 @@ -145,7 +145,7 @@ def decode(input, output, header=False): new = new + c; i = i+1 elif i+1 == n and not partial: partial = 1; break - elif i+1 < n and line[i+1] == ESCAPE: + elif i+1 < n and line[i+1:i+2] == ESCAPE: new = new + ESCAPE; i = i+2 elif i+2 < n and ishex(line[i+1:i+2]) and ishex(line[i+2:i+3]): new = new + bytes((unhex(line[i+1:i+3]),)); i = i+3 diff -r d478a2a5738a Lib/smtpd.py --- a/Lib/smtpd.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/smtpd.py Fri Mar 20 12:07:07 2015 +0200 @@ -154,7 +154,7 @@ class SMTPChannel(asynchat.async_chat): else: self._emptystring = b'' self._linesep = b'\r\n' - self._dotsep = b'.' + self._dotsep = ord(b'.') self._newline = b'\n' self._set_rset_state() self.seen_greeting = '' diff -r d478a2a5738a Lib/sunau.py --- a/Lib/sunau.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/sunau.py Fri Mar 20 12:07:07 2015 +0200 @@ -210,12 +210,9 @@ class Au_read: self._framesize = self._framesize * self._nchannels if self._hdr_size > 24: self._info = file.read(self._hdr_size - 24) - for i in range(len(self._info)): - if self._info[i] == b'\0': - self._info = self._info[:i] - break + self._info, _, _ = self._info.partition(b'\0') else: - self._info = '' + self._info = b'' try: self._data_pos = file.tell() except (AttributeError, OSError): diff -r d478a2a5738a Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/test/test_buffer.py Fri Mar 20 12:07:07 2015 +0200 @@ -150,15 +150,15 @@ def randrange_fmt(mode, char, obj): format character.""" x = randrange(*fmtdict[mode][char]) if char == 'c': - x = bytes(chr(x), 'latin1') + x = bytes([x]) + if obj == 'numpy' and x == b'\x00': + # http://projects.scipy.org/numpy/ticket/1925 + x = b'\x01' if char == '?': x = bool(x) if char == 'f' or char == 'd': x = struct.pack(char, x) x = struct.unpack(char, x)[0] - if obj == 'numpy' and x == b'\x00': - # http://projects.scipy.org/numpy/ticket/1925 - x = b'\x01' return x def gen_item(fmt, obj): diff -r d478a2a5738a Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/test/test_bytes.py Fri Mar 20 12:07:07 2015 +0200 @@ -1338,20 +1338,35 @@ class AssortedBytesTest(unittest.TestCas b = bytearray() self.assertFalse(b.replace(b'', b'') is b) + @unittest.skipUnless(sys.flags.bytes_warning, + "BytesWarning is needed for this test: use -bb option") def test_compare(self): - if sys.flags.bytes_warning: - def bytes_warning(): - return test.support.check_warnings(('', BytesWarning)) - with bytes_warning(): - b'' == '' - with bytes_warning(): - b'' != '' - with bytes_warning(): - bytearray(b'') == '' - with bytes_warning(): - bytearray(b'') != '' - else: - self.skipTest("BytesWarning is needed for this test: use -bb option") + def bytes_warning(): + return test.support.check_warnings(('', BytesWarning)) + with bytes_warning(): + b'' == '' + with bytes_warning(): + '' == b'' + with bytes_warning(): + b'' != '' + with bytes_warning(): + '' != b'' + with bytes_warning(): + bytearray(b'') == '' + with bytes_warning(): + '' == bytearray(b'') + with bytes_warning(): + bytearray(b'') != '' + with bytes_warning(): + '' != bytearray(b'') + with bytes_warning(): + b'\0' == 0 + with bytes_warning(): + 0 == b'\0' + with bytes_warning(): + b'\0' != 0 + with bytes_warning(): + 0 != b'\0' # Optimizations: # __iter__? (optimization) diff -r d478a2a5738a Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py Fri Mar 20 10:37:34 2015 +0100 +++ b/Lib/test/test_tokenize.py Fri Mar 20 12:07:07 2015 +0200 @@ -1068,7 +1068,7 @@ class TestTokenize(TestCase): encoding = object() encoding_used = None def mock_detect_encoding(readline): - return encoding, ['first', 'second'] + return encoding, [b'first', b'second'] def mock__tokenize(readline, encoding): nonlocal encoding_used @@ -1087,7 +1087,7 @@ class TestTokenize(TestCase): counter += 1 if counter == 5: return b'' - return counter + return str(counter).encode() orig_detect_encoding = tokenize_module.detect_encoding orig__tokenize = tokenize_module._tokenize @@ -1095,7 +1095,8 @@ class TestTokenize(TestCase): tokenize_module._tokenize = mock__tokenize try: results = tokenize(mock_readline) - self.assertEqual(list(results), ['first', 'second', 1, 2, 3, 4]) + self.assertEqual(list(results), + [b'first', b'second', b'1', b'2', b'3', b'4']) finally: tokenize_module.detect_encoding = orig_detect_encoding tokenize_module._tokenize = orig__tokenize diff -r d478a2a5738a Objects/bytesobject.c --- a/Objects/bytesobject.c Fri Mar 20 10:37:34 2015 +0100 +++ b/Objects/bytesobject.c Fri Mar 20 12:07:07 2015 +0200 @@ -1385,14 +1385,23 @@ bytes_richcompare(PyBytesObject *a, PyBy /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { - if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE) && - (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyUnicode_Type))) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and string", 1)) - return NULL; + if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { + if (PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyUnicode_Type) || + PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyUnicode_Type)) { + if (PyErr_WarnEx(PyExc_BytesWarning, + "Comparison between bytes and string", 1)) + return NULL; + } + else if (PyObject_IsInstance((PyObject*)a, + (PyObject*)&PyLong_Type) || + PyObject_IsInstance((PyObject*)b, + (PyObject*)&PyLong_Type)) { + if (PyErr_WarnEx(PyExc_BytesWarning, + "Comparison between bytes and int", 1)) + return NULL; + } } result = Py_NotImplemented; }