diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2012-01-12 21:46:19 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2012-01-12 21:46:19 (GMT) |
commit | 3a5d4cb940d9f06505b0b65916fd9a844bed13e3 (patch) | |
tree | 4f76dccee7b943c2d421442240892fe711401053 | |
parent | b63a450cc4c69c4e8668aa434a37b2aa213e94e0 (diff) | |
download | cpython-3a5d4cb940d9f06505b0b65916fd9a844bed13e3.zip cpython-3a5d4cb940d9f06505b0b65916fd9a844bed13e3.tar.gz cpython-3a5d4cb940d9f06505b0b65916fd9a844bed13e3.tar.bz2 |
Issue #13748: Raw bytes literals can now be written with the `rb` prefix as well as `br`.
-rw-r--r-- | Doc/reference/lexical_analysis.rst | 6 | ||||
-rw-r--r-- | Lib/test/test_strlit.py | 21 | ||||
-rw-r--r-- | Lib/test/tokenize_tests.txt | 8 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Parser/tokenizer.c | 16 | ||||
-rw-r--r-- | Python/ast.c | 19 |
6 files changed, 54 insertions, 19 deletions
diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 5900daa..c20c47e 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -412,7 +412,7 @@ String literals are described by the following lexical definitions: .. productionlist:: bytesliteral: `bytesprefix`(`shortbytes` | `longbytes`) - bytesprefix: "b" | "B" | "br" | "Br" | "bR" | "BR" + bytesprefix: "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" shortbytes: "'" `shortbytesitem`* "'" | '"' `shortbytesitem`* '"' longbytes: "'''" `longbytesitem`* "'''" | '"""' `longbytesitem`* '"""' shortbytesitem: `shortbyteschar` | `bytesescapeseq` @@ -446,6 +446,10 @@ or ``'R'``; such strings are called :dfn:`raw strings` and treat backslashes as literal characters. As a result, in string literals, ``'\U'`` and ``'\u'`` escapes in raw strings are not treated specially. + .. versionadded:: 3.3 + The ``'rb'`` prefix of raw bytes literals has been added as a synonym + of ``'br'``. + In triple-quoted strings, unescaped newlines and quotes are allowed (and are retained), except that three unescaped quotes in a row terminate the string. (A "quote" is the character used to open the string, i.e. either ``'`` or ``"``.) diff --git a/Lib/test/test_strlit.py b/Lib/test/test_strlit.py index dbf8652..a6033a4 100644 --- a/Lib/test/test_strlit.py +++ b/Lib/test/test_strlit.py @@ -2,10 +2,10 @@ r"""Test correct treatment of various string literals by the parser. There are four types of string literals: - 'abc' -- normal str - r'abc' -- raw str - b'xyz' -- normal bytes - br'xyz' -- raw bytes + 'abc' -- normal str + r'abc' -- raw str + b'xyz' -- normal bytes + br'xyz' | rb'xyz' -- raw bytes The difference between normal and raw strings is of course that in a raw string, \ escapes (while still used to determine the end of the @@ -103,12 +103,25 @@ class TestLiterals(unittest.TestCase): def test_eval_bytes_raw(self): self.assertEqual(eval(""" br'x' """), b'x') + self.assertEqual(eval(""" rb'x' """), b'x') self.assertEqual(eval(r""" br'\x01' """), b'\\' + b'x01') + self.assertEqual(eval(r""" rb'\x01' """), b'\\' + b'x01') self.assertEqual(eval(""" br'\x01' """), byte(1)) + self.assertEqual(eval(""" rb'\x01' """), byte(1)) self.assertEqual(eval(r""" br'\x81' """), b"\\" + b"x81") + self.assertEqual(eval(r""" rb'\x81' """), b"\\" + b"x81") self.assertRaises(SyntaxError, eval, """ br'\x81' """) + self.assertRaises(SyntaxError, eval, """ rb'\x81' """) self.assertEqual(eval(r""" br'\u1881' """), b"\\" + b"u1881") + self.assertEqual(eval(r""" rb'\u1881' """), b"\\" + b"u1881") self.assertRaises(SyntaxError, eval, """ br'\u1881' """) + self.assertRaises(SyntaxError, eval, """ rb'\u1881' """) + self.assertRaises(SyntaxError, eval, """ bb'' """) + self.assertRaises(SyntaxError, eval, """ rr'' """) + self.assertRaises(SyntaxError, eval, """ brr'' """) + self.assertRaises(SyntaxError, eval, """ bbr'' """) + self.assertRaises(SyntaxError, eval, """ rrb'' """) + self.assertRaises(SyntaxError, eval, """ rbb'' """) def check_encoding(self, encoding, extra=""): modname = "xx_" + encoding.replace("-", "_") diff --git a/Lib/test/tokenize_tests.txt b/Lib/test/tokenize_tests.txt index 06c83b0..2c5fb10 100644 --- a/Lib/test/tokenize_tests.txt +++ b/Lib/test/tokenize_tests.txt @@ -114,8 +114,12 @@ x = b'abc' + B'ABC' y = b"abc" + B"ABC" x = br'abc' + Br'ABC' + bR'ABC' + BR'ABC' y = br"abc" + Br"ABC" + bR"ABC" + BR"ABC" +x = rb'abc' + rB'ABC' + Rb'ABC' + RB'ABC' +y = rb"abc" + rB"ABC" + Rb"ABC" + RB"ABC" x = br'\\' + BR'\\' +x = rb'\\' + RB'\\' x = br'\'' + '' +x = rb'\'' + '' y = br''' foo bar \\ baz''' + BR''' @@ -124,6 +128,10 @@ y = Br"""foo bar \\ baz """ + bR'''spam ''' +y = rB"""foo +bar \\ baz +""" + Rb'''spam +''' # Indentation if 1: @@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1? Core and Builtins ----------------- +- Issue #13748: Raw bytes literals can now be written with the ``rb`` prefix + as well as ``br``. + - Issue #12736: Use full unicode case mappings for upper, lower, and title case. - Issue #12760: Add a create mode to open(). Patch by David Townshend. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index c3b2f35..55f4313 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1412,13 +1412,15 @@ tok_get(register struct tok_state *tok, char **p_start, char **p_end) /* Identifier (most frequent token!) */ nonascii = 0; if (is_potential_identifier_start(c)) { - /* Process b"", r"" and br"" */ - if (c == 'b' || c == 'B') { - c = tok_nextc(tok); - if (c == '"' || c == '\'') - goto letter_quote; - } - if (c == 'r' || c == 'R') { + /* Process b"", r"", br"" and rb"" */ + int saw_b = 0, saw_r = 0; + while (1) { + if (!saw_b && (c == 'b' || c == 'B')) + saw_b = 1; + else if (!saw_r && (c == 'r' || c == 'R')) + saw_r = 1; + else + break; c = tok_nextc(tok); if (c == '"' || c == '\'') goto letter_quote; diff --git a/Python/ast.c b/Python/ast.c index 48aef48..110754b 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3744,13 +3744,18 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) int rawmode = 0; int need_encoding; if (isalpha(quote)) { - if (quote == 'b' || quote == 'B') { - quote = *++s; - *bytesmode = 1; - } - if (quote == 'r' || quote == 'R') { - quote = *++s; - rawmode = 1; + while (!*bytesmode || !rawmode) { + if (quote == 'b' || quote == 'B') { + quote = *++s; + *bytesmode = 1; + } + else if (quote == 'r' || quote == 'R') { + quote = *++s; + rawmode = 1; + } + else { + break; + } } } if (quote != '\'' && quote != '\"') { |