Compare commits
4 Commits
607501abb4
...
bd2728b1e8
Author | SHA1 | Date |
---|---|---|
Pablo Galindo | bd2728b1e8 | |
Lysandros Nikolaou | 2ea320dddd | |
Raymond Hettinger | 8f8de7380c | |
Raymond Hettinger | 768fa145cf |
|
@ -580,18 +580,23 @@ star_targets[expr_ty]:
|
||||||
| a=star_target !',' { a }
|
| a=star_target !',' { a }
|
||||||
| a=star_target b=(',' c=star_target { c })* [','] {
|
| a=star_target b=(',' c=star_target { c })* [','] {
|
||||||
_Py_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Store, EXTRA) }
|
_Py_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Store, EXTRA) }
|
||||||
star_targets_seq[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_target+ [','] { a }
|
star_targets_list_seq[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_target+ [','] { a }
|
||||||
|
star_targets_tuple_seq[asdl_expr_seq*]:
|
||||||
|
| a=star_target b=(',' c=star_target { c })+ [','] { (asdl_expr_seq*) _PyPegen_seq_insert_in_front(p, a, b) }
|
||||||
|
| a=star_target ',' { (asdl_expr_seq*) _PyPegen_singleton_seq(p, a) }
|
||||||
star_target[expr_ty] (memo):
|
star_target[expr_ty] (memo):
|
||||||
| '*' a=(!'*' star_target) {
|
| '*' a=(!'*' star_target) {
|
||||||
_Py_Starred(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), Store, EXTRA) }
|
_Py_Starred(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), Store, EXTRA) }
|
||||||
|
| target_with_star_atom
|
||||||
|
target_with_star_atom[expr_ty] (memo):
|
||||||
| a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
| a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
||||||
| a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Store, EXTRA) }
|
| a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Store, EXTRA) }
|
||||||
| star_atom
|
| star_atom
|
||||||
star_atom[expr_ty]:
|
star_atom[expr_ty]:
|
||||||
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
||||||
| '(' a=star_target ')' { _PyPegen_set_expr_context(p, a, Store) }
|
| '(' a=target_with_star_atom ')' { _PyPegen_set_expr_context(p, a, Store) }
|
||||||
| '(' a=[star_targets_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
|
| '(' a=[star_targets_tuple_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
|
||||||
| '[' a=[star_targets_seq] ']' { _Py_List(a, Store, EXTRA) }
|
| '[' a=[star_targets_list_seq] ']' { _Py_List(a, Store, EXTRA) }
|
||||||
|
|
||||||
single_target[expr_ty]:
|
single_target[expr_ty]:
|
||||||
| single_subscript_attribute_target
|
| single_subscript_attribute_target
|
||||||
|
|
|
@ -96,6 +96,7 @@ LOG4 = _log(4.0)
|
||||||
SG_MAGICCONST = 1.0 + _log(4.5)
|
SG_MAGICCONST = 1.0 + _log(4.5)
|
||||||
BPF = 53 # Number of bits in a float
|
BPF = 53 # Number of bits in a float
|
||||||
RECIP_BPF = 2 ** -BPF
|
RECIP_BPF = 2 ** -BPF
|
||||||
|
_ONE = 1
|
||||||
|
|
||||||
|
|
||||||
class Random(_random.Random):
|
class Random(_random.Random):
|
||||||
|
@ -288,7 +289,7 @@ class Random(_random.Random):
|
||||||
|
|
||||||
## -------------------- integer methods -------------------
|
## -------------------- integer methods -------------------
|
||||||
|
|
||||||
def randrange(self, start, stop=None, step=1):
|
def randrange(self, start, stop=None, step=_ONE):
|
||||||
"""Choose a random item from range(start, stop[, step]).
|
"""Choose a random item from range(start, stop[, step]).
|
||||||
|
|
||||||
This fixes the problem with randint() which includes the
|
This fixes the problem with randint() which includes the
|
||||||
|
@ -311,7 +312,12 @@ class Random(_random.Random):
|
||||||
_warn('randrange() will raise TypeError in the future',
|
_warn('randrange() will raise TypeError in the future',
|
||||||
DeprecationWarning, 2)
|
DeprecationWarning, 2)
|
||||||
raise ValueError("non-integer arg 1 for randrange()")
|
raise ValueError("non-integer arg 1 for randrange()")
|
||||||
|
|
||||||
if stop is None:
|
if stop is None:
|
||||||
|
# We don't check for "step != 1" because it hasn't been
|
||||||
|
# type checked and converted to an integer yet.
|
||||||
|
if step is not _ONE:
|
||||||
|
raise TypeError('Missing a non-None stop argument')
|
||||||
if istart > 0:
|
if istart > 0:
|
||||||
return self._randbelow(istart)
|
return self._randbelow(istart)
|
||||||
raise ValueError("empty range for randrange()")
|
raise ValueError("empty range for randrange()")
|
||||||
|
@ -345,9 +351,9 @@ class Random(_random.Random):
|
||||||
DeprecationWarning, 2)
|
DeprecationWarning, 2)
|
||||||
raise ValueError("non-integer step for randrange()")
|
raise ValueError("non-integer step for randrange()")
|
||||||
width = istop - istart
|
width = istop - istart
|
||||||
if istep == 1 and width > 0:
|
|
||||||
return istart + self._randbelow(width)
|
|
||||||
if istep == 1:
|
if istep == 1:
|
||||||
|
if width > 0:
|
||||||
|
return istart + self._randbelow(width)
|
||||||
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
|
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
|
||||||
|
|
||||||
# Non-unit step argument supplied.
|
# Non-unit step argument supplied.
|
||||||
|
@ -357,10 +363,8 @@ class Random(_random.Random):
|
||||||
n = (width + istep + 1) // istep
|
n = (width + istep + 1) // istep
|
||||||
else:
|
else:
|
||||||
raise ValueError("zero step for randrange()")
|
raise ValueError("zero step for randrange()")
|
||||||
|
|
||||||
if n <= 0:
|
if n <= 0:
|
||||||
raise ValueError("empty range for randrange()")
|
raise ValueError("empty range for randrange()")
|
||||||
|
|
||||||
return istart + istep * self._randbelow(n)
|
return istart + istep * self._randbelow(n)
|
||||||
|
|
||||||
def randint(self, a, b):
|
def randint(self, a, b):
|
||||||
|
|
|
@ -332,6 +332,59 @@ non-important content
|
||||||
self.assertEqual(binop.left.col_offset, 4)
|
self.assertEqual(binop.left.col_offset, 4)
|
||||||
self.assertEqual(binop.right.col_offset, 7)
|
self.assertEqual(binop.right.col_offset, 7)
|
||||||
|
|
||||||
|
def test_ast_line_numbers_with_parentheses(self):
|
||||||
|
expr = """
|
||||||
|
x = (
|
||||||
|
f" {test(t)}"
|
||||||
|
)"""
|
||||||
|
t = ast.parse(expr)
|
||||||
|
self.assertEqual(type(t), ast.Module)
|
||||||
|
self.assertEqual(len(t.body), 1)
|
||||||
|
# check the test(t) location
|
||||||
|
call = t.body[0].value.values[1].value
|
||||||
|
self.assertEqual(type(call), ast.Call)
|
||||||
|
self.assertEqual(call.lineno, 3)
|
||||||
|
self.assertEqual(call.end_lineno, 3)
|
||||||
|
self.assertEqual(call.col_offset, 8)
|
||||||
|
self.assertEqual(call.end_col_offset, 15)
|
||||||
|
|
||||||
|
expr = """
|
||||||
|
x = (
|
||||||
|
'PERL_MM_OPT', (
|
||||||
|
f'wat'
|
||||||
|
f'some_string={f(x)} '
|
||||||
|
f'wat'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
t = ast.parse(expr)
|
||||||
|
self.assertEqual(type(t), ast.Module)
|
||||||
|
self.assertEqual(len(t.body), 1)
|
||||||
|
# check the fstring
|
||||||
|
fstring = t.body[0].value.elts[1]
|
||||||
|
self.assertEqual(type(fstring), ast.JoinedStr)
|
||||||
|
self.assertEqual(len(fstring.values), 3)
|
||||||
|
wat1, middle, wat2 = fstring.values
|
||||||
|
# check the first wat
|
||||||
|
self.assertEqual(type(wat1), ast.Constant)
|
||||||
|
self.assertEqual(wat1.lineno, 4)
|
||||||
|
self.assertEqual(wat1.end_lineno, 6)
|
||||||
|
self.assertEqual(wat1.col_offset, 12)
|
||||||
|
self.assertEqual(wat1.end_col_offset, 18)
|
||||||
|
# check the call
|
||||||
|
call = middle.value
|
||||||
|
self.assertEqual(type(call), ast.Call)
|
||||||
|
self.assertEqual(call.lineno, 5)
|
||||||
|
self.assertEqual(call.end_lineno, 5)
|
||||||
|
self.assertEqual(call.col_offset, 27)
|
||||||
|
self.assertEqual(call.end_col_offset, 31)
|
||||||
|
# check the second wat
|
||||||
|
self.assertEqual(type(wat2), ast.Constant)
|
||||||
|
self.assertEqual(wat2.lineno, 4)
|
||||||
|
self.assertEqual(wat2.end_lineno, 6)
|
||||||
|
self.assertEqual(wat2.col_offset, 12)
|
||||||
|
self.assertEqual(wat2.end_col_offset, 18)
|
||||||
|
|
||||||
def test_docstring(self):
|
def test_docstring(self):
|
||||||
def f():
|
def f():
|
||||||
f'''Not a docstring'''
|
f'''Not a docstring'''
|
||||||
|
|
|
@ -562,6 +562,14 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
randrange(10, 20, 1.5)
|
randrange(10, 20, 1.5)
|
||||||
|
|
||||||
|
def test_randrange_step(self):
|
||||||
|
# bpo-42772: When stop is None, the step argument was being ignored.
|
||||||
|
randrange = self.gen.randrange
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
randrange(1000, step=100)
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
randrange(1000, None, step=100)
|
||||||
|
|
||||||
def test_randbelow_logic(self, _log=log, int=int):
|
def test_randbelow_logic(self, _log=log, int=int):
|
||||||
# check bitcount transition points: 2**i and 2**(i+1)-1
|
# check bitcount transition points: 2**i and 2**(i+1)-1
|
||||||
# show that: k = int(1.001 + _log(n, 2))
|
# show that: k = int(1.001 + _log(n, 2))
|
||||||
|
|
|
@ -346,6 +346,31 @@ Now some general starred expressions (all fail).
|
||||||
...
|
...
|
||||||
SyntaxError: can't use starred expression here
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
|
>>> (*x),y = 1, 2 # doctest:+ELLIPSIS
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
|
>>> (((*x))),y = 1, 2 # doctest:+ELLIPSIS
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
|
>>> z,(*x),y = 1, 2, 4 # doctest:+ELLIPSIS
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
|
>>> z,(*x) = 1, 2 # doctest:+ELLIPSIS
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
|
>>> ((*x),y) = 1, 2 # doctest:+ELLIPSIS
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: can't use starred expression here
|
||||||
|
|
||||||
Some size constraints (all fail.)
|
Some size constraints (all fail.)
|
||||||
|
|
||||||
>>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
|
>>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix regression where a single parenthesized starred expression was a valid
|
||||||
|
assignment target.
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix the column offsets for f-strings :mod:`ast` nodes surrounded by
|
||||||
|
parentheses and for nodes that spawn multiple lines. Patch by Pablo Galindo.
|
|
@ -0,0 +1,2 @@
|
||||||
|
randrange() now raises a TypeError when step is specified without a stop
|
||||||
|
argument. Formerly, it silently ignored the step argument.
|
1639
Parser/parser.c
1639
Parser/parser.c
File diff suppressed because it is too large
Load Diff
|
@ -405,7 +405,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
|
||||||
Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
|
Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
|
||||||
NULL, p->arena);
|
NULL, p->arena);
|
||||||
p2->starting_lineno = t->lineno + lines - 1;
|
p2->starting_lineno = t->lineno + lines - 1;
|
||||||
p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
|
p2->starting_col_offset = t->col_offset + cols;
|
||||||
|
|
||||||
expr = _PyPegen_run_parser(p2);
|
expr = _PyPegen_run_parser(p2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue