summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2012-01-12 21:46:19 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2012-01-12 21:46:19 (GMT)
commit3a5d4cb940d9f06505b0b65916fd9a844bed13e3 (patch)
tree4f76dccee7b943c2d421442240892fe711401053
parentb63a450cc4c69c4e8668aa434a37b2aa213e94e0 (diff)
downloadcpython-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.rst6
-rw-r--r--Lib/test/test_strlit.py21
-rw-r--r--Lib/test/tokenize_tests.txt8
-rw-r--r--Misc/NEWS3
-rw-r--r--Parser/tokenizer.c16
-rw-r--r--Python/ast.c19
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:
diff --git a/Misc/NEWS b/Misc/NEWS
index 4cfccae..d930f15 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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 != '\"') {