mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Uodate test_grammar.py from 3.13.7
This commit is contained in:
1 parent
d9ffc47c43
commit
6a4d4b727c
1 file changed
+310
-140
Vendored
+310
-140
@@ -2,7 +2,7 @@
|
||||
# This just tests whether the parser accepts them all.
|
||||
|
||||
from test.support import check_syntax_error
|
||||
from test.support.warnings_helper import check_syntax_warning
|
||||
from test.support import import_helper
|
||||
import inspect
|
||||
import unittest
|
||||
import sys
|
||||
@@ -12,97 +12,19 @@ from sys import *
|
||||
|
||||
# different import patterns to check that __annotations__ does not interfere
|
||||
# with import machinery
|
||||
# import test.ann_module as ann_module
|
||||
import test.typinganndata.ann_module as ann_module
|
||||
import typing
|
||||
from collections import ChainMap
|
||||
# from test import ann_module2
|
||||
from test.typinganndata import ann_module2
|
||||
import test
|
||||
|
||||
# These are shared with test_tokenize and other test modules.
|
||||
#
|
||||
# Note: since several test cases filter out floats by looking for "e" and ".",
|
||||
# don't add hexadecimal literals that contain "e" or "E".
|
||||
VALID_UNDERSCORE_LITERALS = [
|
||||
'0_0_0',
|
||||
'4_2',
|
||||
'1_0000_0000',
|
||||
'0b1001_0100',
|
||||
'0xffff_ffff',
|
||||
'0o5_7_7',
|
||||
'1_00_00.5',
|
||||
'1_00_00.5e5',
|
||||
'1_00_00e5_1',
|
||||
'1e1_0',
|
||||
'.1_4',
|
||||
'.1_4e1',
|
||||
'0b_0',
|
||||
'0x_f',
|
||||
'0o_5',
|
||||
'1_00_00j',
|
||||
'1_00_00.5j',
|
||||
'1_00_00e5_1j',
|
||||
'.1_4j',
|
||||
'(1_2.5+3_3j)',
|
||||
'(.5_6j)',
|
||||
]
|
||||
INVALID_UNDERSCORE_LITERALS = [
|
||||
# Trailing underscores:
|
||||
'0_',
|
||||
'42_',
|
||||
'1.4j_',
|
||||
'0x_',
|
||||
'0b1_',
|
||||
'0xf_',
|
||||
'0o5_',
|
||||
'0 if 1_Else 1',
|
||||
# Underscores in the base selector:
|
||||
'0_b0',
|
||||
'0_xf',
|
||||
'0_o5',
|
||||
# Old-style octal, still disallowed:
|
||||
'0_7',
|
||||
'09_99',
|
||||
# Multiple consecutive underscores:
|
||||
'4_______2',
|
||||
'0.1__4',
|
||||
'0.1__4j',
|
||||
'0b1001__0100',
|
||||
'0xffff__ffff',
|
||||
'0x___',
|
||||
'0o5__77',
|
||||
'1e1__0',
|
||||
'1e1__0j',
|
||||
# Underscore right before a dot:
|
||||
'1_.4',
|
||||
'1_.4j',
|
||||
# Underscore right after a dot:
|
||||
'1._4',
|
||||
'1._4j',
|
||||
'._5',
|
||||
'._5j',
|
||||
# Underscore right after a sign:
|
||||
'1.0e+_1',
|
||||
'1.0e+_1j',
|
||||
# Underscore right before j:
|
||||
'1.4_j',
|
||||
'1.4e5_j',
|
||||
# Underscore right before e:
|
||||
'1_e1',
|
||||
'1.4_e1',
|
||||
'1.4_e1j',
|
||||
# Underscore right after e:
|
||||
'1e_1',
|
||||
'1.4e_1',
|
||||
'1.4e_1j',
|
||||
# Complex cases with parens:
|
||||
'(1+1.5_j_)',
|
||||
'(1+1.5_j)',
|
||||
]
|
||||
|
||||
from test.support.numbers import (
|
||||
VALID_UNDERSCORE_LITERALS,
|
||||
INVALID_UNDERSCORE_LITERALS,
|
||||
)
|
||||
|
||||
class TokenTests(unittest.TestCase):
|
||||
|
||||
from test.support import check_syntax_error
|
||||
from test.support.warnings_helper import check_syntax_warning
|
||||
|
||||
def test_backslash(self):
|
||||
# Backslash means line continuation:
|
||||
@@ -164,7 +86,7 @@ class TokenTests(unittest.TestCase):
|
||||
x = 3.14
|
||||
x = 314.
|
||||
x = 0.314
|
||||
# XXX x = 000.314
|
||||
x = 000.314
|
||||
x = .314
|
||||
x = 3e14
|
||||
x = 3E14
|
||||
@@ -176,8 +98,10 @@ class TokenTests(unittest.TestCase):
|
||||
|
||||
def test_float_exponent_tokenization(self):
|
||||
# See issue 21642.
|
||||
self.assertEqual(1 if 1else 0, 1)
|
||||
self.assertEqual(1 if 0else 0, 0)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', SyntaxWarning)
|
||||
self.assertEqual(eval("1 if 1else 0"), 1)
|
||||
self.assertEqual(eval("1 if 0else 0"), 0)
|
||||
self.assertRaises(SyntaxError, eval, "0 if 1Else 0")
|
||||
|
||||
def test_underscore_literals(self):
|
||||
@@ -188,8 +112,7 @@ class TokenTests(unittest.TestCase):
|
||||
# Sanity check: no literal begins with an underscore
|
||||
self.assertRaises(NameError, eval, "_0")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_bad_numerical_literals(self):
|
||||
check = self.check_syntax_error
|
||||
check("0b12", "invalid digit '2' in binary literal")
|
||||
@@ -212,6 +135,47 @@ class TokenTests(unittest.TestCase):
|
||||
check("1e2_", "invalid decimal literal")
|
||||
check("1e+", "invalid decimal literal")
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_end_of_numerical_literals(self):
|
||||
def check(test, error=False):
|
||||
with self.subTest(expr=test):
|
||||
if error:
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r'invalid \w+ literal'):
|
||||
compile(test, "<testcase>", "eval")
|
||||
self.assertEqual(w, [])
|
||||
else:
|
||||
self.check_syntax_warning(test,
|
||||
errtext=r'invalid \w+ literal')
|
||||
|
||||
for num in "0xf", "0o7", "0b1", "9", "0", "1.", "1e3", "1j":
|
||||
compile(num, "<testcase>", "eval")
|
||||
check(f"{num}and x", error=(num == "0xf"))
|
||||
check(f"{num}or x", error=(num == "0"))
|
||||
check(f"{num}in x")
|
||||
check(f"{num}not in x")
|
||||
check(f"{num}if x else y")
|
||||
check(f"x if {num}else y", error=(num == "0xf"))
|
||||
check(f"[{num}for x in ()]")
|
||||
check(f"{num}spam", error=True)
|
||||
|
||||
# gh-88943: Invalid non-ASCII character following a numerical literal.
|
||||
with self.assertRaisesRegex(SyntaxError, r"invalid character '⁄' \(U\+2044\)"):
|
||||
compile(f"{num}⁄7", "<testcase>", "eval")
|
||||
|
||||
with self.assertWarnsRegex(SyntaxWarning, r'invalid \w+ literal'):
|
||||
compile(f"{num}is x", "<testcase>", "eval")
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('error', SyntaxWarning)
|
||||
with self.assertRaisesRegex(SyntaxError,
|
||||
r'invalid \w+ literal'):
|
||||
compile(f"{num}is x", "<testcase>", "eval")
|
||||
|
||||
check("[0x1ffor x in ()]")
|
||||
check("[0x1for x in ()]")
|
||||
check("[0xfor x in ()]")
|
||||
|
||||
def test_string_literals(self):
|
||||
x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y)
|
||||
x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39)
|
||||
@@ -257,12 +221,13 @@ the \'lazy\' dog.\n\
|
||||
self.assertTrue(x is Ellipsis)
|
||||
self.assertRaises(SyntaxError, eval, ".. .")
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_eof_error(self):
|
||||
samples = ("def foo(", "\ndef foo(", "def foo(\n")
|
||||
for s in samples:
|
||||
with self.assertRaises(SyntaxError) as cm:
|
||||
compile(s, "<test>", "exec")
|
||||
self.assertIn("unexpected EOF", str(cm.exception))
|
||||
self.assertIn("was never closed", str(cm.exception))
|
||||
|
||||
var_annot_global: int # a global annotated is necessary for test_var_annot
|
||||
|
||||
@@ -281,6 +246,7 @@ class GrammarTests(unittest.TestCase):
|
||||
|
||||
from test.support import check_syntax_error
|
||||
from test.support.warnings_helper import check_syntax_warning
|
||||
from test.support.warnings_helper import check_no_warnings
|
||||
|
||||
# single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
|
||||
# XXX can't test in a script -- this rule is only used when interactive
|
||||
@@ -307,14 +273,18 @@ class GrammarTests(unittest.TestCase):
|
||||
my_lst[one()-1]: int = 5
|
||||
self.assertEqual(my_lst, [5])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_var_annot_syntax_errors(self):
|
||||
# parser pass
|
||||
check_syntax_error(self, "def f: int")
|
||||
check_syntax_error(self, "x: int: str")
|
||||
check_syntax_error(self, "def f():\n"
|
||||
" nonlocal x: int\n")
|
||||
check_syntax_error(self, "def f():\n"
|
||||
" global x: int\n")
|
||||
check_syntax_error(self, "x: int = y = 1")
|
||||
check_syntax_error(self, "z = w: int = 1")
|
||||
check_syntax_error(self, "x: int = y: int = 1")
|
||||
# AST pass
|
||||
check_syntax_error(self, "[x, 0]: int\n")
|
||||
check_syntax_error(self, "f(): int\n")
|
||||
@@ -328,9 +298,14 @@ class GrammarTests(unittest.TestCase):
|
||||
check_syntax_error(self, "def f():\n"
|
||||
" global x\n"
|
||||
" x: int\n")
|
||||
check_syntax_error(self, "def f():\n"
|
||||
" x: int\n"
|
||||
" nonlocal x\n")
|
||||
check_syntax_error(self, "def f():\n"
|
||||
" nonlocal x\n"
|
||||
" x: int\n")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_var_annot_basic_semantics(self):
|
||||
# execution order
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
@@ -377,6 +352,28 @@ class GrammarTests(unittest.TestCase):
|
||||
x: int
|
||||
x.y: list = []
|
||||
|
||||
def test_annotations_inheritance(self):
|
||||
# Check that annotations are not inherited by derived classes
|
||||
class A:
|
||||
attr: int
|
||||
class B(A):
|
||||
pass
|
||||
class C(A):
|
||||
attr: str
|
||||
class D:
|
||||
attr2: int
|
||||
class E(A, D):
|
||||
pass
|
||||
class F(C, A):
|
||||
pass
|
||||
self.assertEqual(A.__annotations__, {"attr": int})
|
||||
self.assertEqual(B.__annotations__, {})
|
||||
self.assertEqual(C.__annotations__, {"attr" : str})
|
||||
self.assertEqual(D.__annotations__, {"attr2" : int})
|
||||
self.assertEqual(E.__annotations__, {})
|
||||
self.assertEqual(F.__annotations__, {})
|
||||
|
||||
|
||||
def test_var_annot_metaclass_semantics(self):
|
||||
class CMeta(type):
|
||||
@classmethod
|
||||
@@ -386,13 +383,11 @@ class GrammarTests(unittest.TestCase):
|
||||
XX: 'ANNOT'
|
||||
self.assertEqual(CC.__annotations__['xx'], 'ANNOT')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_var_annot_module_semantics(self):
|
||||
with self.assertRaises(AttributeError):
|
||||
print(test.__annotations__)
|
||||
self.assertEqual(test.__annotations__, {})
|
||||
self.assertEqual(ann_module.__annotations__,
|
||||
{1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int]})
|
||||
{1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int], 'u': int | float})
|
||||
self.assertEqual(ann_module.M.__annotations__,
|
||||
{'123': 123, 'o': type})
|
||||
self.assertEqual(ann_module2.__annotations__, {})
|
||||
@@ -400,13 +395,13 @@ class GrammarTests(unittest.TestCase):
|
||||
def test_var_annot_in_module(self):
|
||||
# check that functions fail the same way when executed
|
||||
# outside of module where they were defined
|
||||
from test.typinganndata.ann_module3 import f_bad_ann, g_bad_ann, D_bad_ann
|
||||
ann_module3 = import_helper.import_fresh_module("test.typinganndata.ann_module3")
|
||||
with self.assertRaises(NameError):
|
||||
f_bad_ann()
|
||||
ann_module3.f_bad_ann()
|
||||
with self.assertRaises(NameError):
|
||||
g_bad_ann()
|
||||
ann_module3.g_bad_ann()
|
||||
with self.assertRaises(NameError):
|
||||
D_bad_ann(5)
|
||||
ann_module3.D_bad_ann(5)
|
||||
|
||||
def test_var_annot_simple_exec(self):
|
||||
gns = {}; lns= {}
|
||||
@@ -417,8 +412,7 @@ class GrammarTests(unittest.TestCase):
|
||||
with self.assertRaises(KeyError):
|
||||
gns['__annotations__']
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_var_annot_custom_maps(self):
|
||||
# tests with custom locals() and __annotations__
|
||||
ns = {'__annotations__': CNS()}
|
||||
@@ -440,8 +434,7 @@ class GrammarTests(unittest.TestCase):
|
||||
exec('x: int = 1', {}, CNS2())
|
||||
self.assertEqual(nonloc_ns['__annotations__']['x'], int)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_var_annot_refleak(self):
|
||||
# complex case: custom locals plus custom __annotations__
|
||||
# this was causing refleak
|
||||
@@ -459,7 +452,6 @@ class GrammarTests(unittest.TestCase):
|
||||
exec('X: str', {}, CNS2())
|
||||
self.assertEqual(nonloc_ns['__annotations__']['x'], str)
|
||||
|
||||
|
||||
def test_var_annot_rhs(self):
|
||||
ns = {}
|
||||
exec('x: tuple = 1, 2', ns)
|
||||
@@ -475,7 +467,7 @@ class GrammarTests(unittest.TestCase):
|
||||
|
||||
def test_funcdef(self):
|
||||
### [decorators] 'def' NAME parameters ['->' test] ':' suite
|
||||
### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
||||
### decorator: '@' namedexpr_test NEWLINE
|
||||
### decorators: decorator+
|
||||
### parameters: '(' [typedargslist] ')'
|
||||
### typedargslist: ((tfpdef ['=' test] ',')*
|
||||
@@ -597,12 +589,14 @@ class GrammarTests(unittest.TestCase):
|
||||
d22v(1, *(2, 3), **{'d': 4})
|
||||
|
||||
# keyword argument type tests
|
||||
try:
|
||||
str('x', **{b'foo':1 })
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Bytes should not work as keyword argument names')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', BytesWarning)
|
||||
try:
|
||||
str('x', **{b'foo':1 })
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Bytes should not work as keyword argument names')
|
||||
# keyword only argument tests
|
||||
def pos0key1(*, key): return key
|
||||
pos0key1(key=100)
|
||||
@@ -681,6 +675,20 @@ class GrammarTests(unittest.TestCase):
|
||||
def f(x) -> list: pass
|
||||
self.assertEqual(f.__annotations__, {'return': list})
|
||||
|
||||
# Test expressions as decorators (PEP 614):
|
||||
@False or null
|
||||
def f(x): pass
|
||||
@d := null
|
||||
def f(x): pass
|
||||
@lambda f: null(f)
|
||||
def f(x): pass
|
||||
@[..., null, ...][1]
|
||||
def f(x): pass
|
||||
@null(null)(null)
|
||||
def f(x): pass
|
||||
@[null][0].__call__.__call__
|
||||
def f(x): pass
|
||||
|
||||
# test closures with a variety of opargs
|
||||
closure = 1
|
||||
def f(): return closure
|
||||
@@ -768,10 +776,9 @@ class GrammarTests(unittest.TestCase):
|
||||
check_syntax_error(self, "x + 1 = 1")
|
||||
check_syntax_error(self, "a + 1 = b + 2")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# Check the heuristic for print & exec covers significant cases
|
||||
# As well as placing some limits on false positives
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_former_statements_refer_to_builtins(self):
|
||||
keywords = "print", "exec"
|
||||
# Cases where we want the custom error
|
||||
@@ -804,6 +811,23 @@ class GrammarTests(unittest.TestCase):
|
||||
del abc
|
||||
del x, y, (z, xyz)
|
||||
|
||||
x, y, z = "xyz"
|
||||
del x
|
||||
del y,
|
||||
del (z)
|
||||
del ()
|
||||
|
||||
a, b, c, d, e, f, g = "abcdefg"
|
||||
del a, (b, c), (d, (e, f))
|
||||
|
||||
a, b, c, d, e, f, g = "abcdefg"
|
||||
del a, [b, c], (d, [e, f])
|
||||
|
||||
abcd = list("abcd")
|
||||
del abcd[1:2]
|
||||
|
||||
compile("del a, (b[0].c, (d.e, f.g[1:2])), [h.i.j], ()", "<testcase>", "exec")
|
||||
|
||||
def test_pass_stmt(self):
|
||||
# 'pass'
|
||||
pass
|
||||
@@ -1062,8 +1086,7 @@ class GrammarTests(unittest.TestCase):
|
||||
self.assertEqual(g2(False), 0)
|
||||
self.assertEqual(g2(True), ('end', 1))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_yield(self):
|
||||
# Allowed as standalone statement
|
||||
def g(): yield 1
|
||||
@@ -1103,8 +1126,7 @@ class GrammarTests(unittest.TestCase):
|
||||
# Check annotation refleak on SyntaxError
|
||||
check_syntax_error(self, "def g(a:(yield)): pass")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_yield_in_comprehensions(self):
|
||||
# Check yield in comprehensions
|
||||
def g(): [x for x in [(yield 1)]]
|
||||
@@ -1184,11 +1206,9 @@ class GrammarTests(unittest.TestCase):
|
||||
self.fail("'assert True, msg' should not have "
|
||||
"raised an AssertionError")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
# these tests fail if python is run with -O, so check __debug__
|
||||
@unittest.skipUnless(__debug__, "Won't work if __debug__ is False")
|
||||
def testAssert2(self):
|
||||
def test_assert_failures(self):
|
||||
try:
|
||||
assert 0, "msg"
|
||||
except AssertionError as e:
|
||||
@@ -1203,11 +1223,38 @@ class GrammarTests(unittest.TestCase):
|
||||
else:
|
||||
self.fail("AssertionError not raised by 'assert False'")
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_syntax_warnings(self):
|
||||
# Ensure that we warn users if they provide a non-zero length tuple as
|
||||
# the assertion test.
|
||||
self.check_syntax_warning('assert(x, "msg")',
|
||||
'assertion is always true')
|
||||
self.check_syntax_warning('assert(False, "msg")',
|
||||
'assertion is always true')
|
||||
self.check_syntax_warning('assert(False,)',
|
||||
'assertion is always true')
|
||||
|
||||
with self.check_no_warnings(category=SyntaxWarning):
|
||||
compile('assert x, "msg"', '<testcase>', 'exec')
|
||||
compile('assert False, "msg"', '<testcase>', 'exec')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_assert_warning_promotes_to_syntax_error(self):
|
||||
# If SyntaxWarning is configured to be an error, it actually raises a
|
||||
# SyntaxError.
|
||||
# https://bugs.python.org/issue35029
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('error', SyntaxWarning)
|
||||
compile('assert x, "msg"', '<testcase>', 'exec')
|
||||
try:
|
||||
compile('assert x, "msg" ', '<testcase>', 'exec')
|
||||
except SyntaxError:
|
||||
self.fail('SyntaxError incorrectly raised for \'assert x, "msg"\'')
|
||||
with self.assertRaises(SyntaxError):
|
||||
compile('assert(x, "msg")', '<testcase>', 'exec')
|
||||
with self.assertRaises(SyntaxError):
|
||||
compile('assert(False, "msg")', '<testcase>', 'exec')
|
||||
with self.assertRaises(SyntaxError):
|
||||
compile('assert(False,)', '<testcase>', 'exec')
|
||||
|
||||
|
||||
### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
||||
@@ -1268,10 +1315,16 @@ class GrammarTests(unittest.TestCase):
|
||||
result.append(x)
|
||||
self.assertEqual(result, [1, 2, 3])
|
||||
|
||||
result = []
|
||||
a = b = c = [1, 2, 3]
|
||||
for x in *a, *b, *c:
|
||||
result.append(x)
|
||||
self.assertEqual(result, 3 * a)
|
||||
|
||||
def test_try(self):
|
||||
### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
|
||||
### | 'try' ':' suite 'finally' ':' suite
|
||||
### except_clause: 'except' [expr ['as' expr]]
|
||||
### except_clause: 'except' [expr ['as' NAME]]
|
||||
try:
|
||||
1/0
|
||||
except ZeroDivisionError:
|
||||
@@ -1289,6 +1342,36 @@ class GrammarTests(unittest.TestCase):
|
||||
except (EOFError, TypeError, ZeroDivisionError) as msg: pass
|
||||
try: pass
|
||||
finally: pass
|
||||
with self.assertRaises(SyntaxError):
|
||||
compile("try:\n pass\nexcept Exception as a.b:\n pass", "?", "exec")
|
||||
compile("try:\n pass\nexcept Exception as a[b]:\n pass", "?", "exec")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
'''
|
||||
def test_try_star(self):
|
||||
### try_stmt: 'try': suite (except_star_clause : suite) + ['else' ':' suite]
|
||||
### except_star_clause: 'except*' expr ['as' NAME]
|
||||
try:
|
||||
1/0
|
||||
except* ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
try: 1/0
|
||||
except* EOFError: pass
|
||||
except* ZeroDivisionError as msg: pass
|
||||
else: pass
|
||||
try: 1/0
|
||||
except* (EOFError, TypeError, ZeroDivisionError): pass
|
||||
try: 1/0
|
||||
except* (EOFError, TypeError, ZeroDivisionError) as msg: pass
|
||||
try: pass
|
||||
finally: pass
|
||||
with self.assertRaises(SyntaxError):
|
||||
compile("try:\n pass\nexcept* Exception as a.b:\n pass", "?", "exec")
|
||||
compile("try:\n pass\nexcept* Exception as a[b]:\n pass", "?", "exec")
|
||||
compile("try:\n pass\nexcept*:\n pass", "?", "exec")
|
||||
'''
|
||||
|
||||
def test_suite(self):
|
||||
# simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
|
||||
@@ -1333,17 +1416,24 @@ class GrammarTests(unittest.TestCase):
|
||||
if 1 not in (): pass
|
||||
if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: pass
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_comparison_is_literal(self):
|
||||
def check(test, msg='"is" with a literal'):
|
||||
def check(test, msg):
|
||||
self.check_syntax_warning(test, msg)
|
||||
|
||||
check('x is 1')
|
||||
check('x is "thing"')
|
||||
check('1 is x')
|
||||
check('x is y is 1')
|
||||
check('x is not 1', '"is not" with a literal')
|
||||
check('x is 1', '"is" with \'int\' literal')
|
||||
check('x is "thing"', '"is" with \'str\' literal')
|
||||
check('1 is x', '"is" with \'int\' literal')
|
||||
check('x is y is 1', '"is" with \'int\' literal')
|
||||
check('x is not 1', '"is not" with \'int\' literal')
|
||||
check('x is not (1, 2)', '"is not" with \'tuple\' literal')
|
||||
check('(1, 2) is not x', '"is not" with \'tuple\' literal')
|
||||
|
||||
check('None is 1', '"is" with \'int\' literal')
|
||||
check('1 is None', '"is" with \'int\' literal')
|
||||
|
||||
check('x == 3 is y', '"is" with \'int\' literal')
|
||||
check('x == "thing" is y', '"is" with \'str\' literal')
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('error', SyntaxWarning)
|
||||
@@ -1351,9 +1441,12 @@ class GrammarTests(unittest.TestCase):
|
||||
compile('x is False', '<testcase>', 'exec')
|
||||
compile('x is True', '<testcase>', 'exec')
|
||||
compile('x is ...', '<testcase>', 'exec')
|
||||
compile('None is x', '<testcase>', 'exec')
|
||||
compile('False is x', '<testcase>', 'exec')
|
||||
compile('True is x', '<testcase>', 'exec')
|
||||
compile('... is x', '<testcase>', 'exec')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_warn_missed_comma(self):
|
||||
def check(test):
|
||||
self.check_syntax_warning(test, msg)
|
||||
@@ -1483,7 +1576,7 @@ class GrammarTests(unittest.TestCase):
|
||||
s = a[-5:]
|
||||
s = a[:-1]
|
||||
s = a[-4:-3]
|
||||
# A rough test of SF bug 1333982. http://python.org/sf/1333982
|
||||
# A rough test of SF bug 1333982. https://bugs.python.org/issue1333982
|
||||
# The testing here is fairly incomplete.
|
||||
# Test cases should include: commas with 1 and 2 colons
|
||||
d = {}
|
||||
@@ -1530,6 +1623,8 @@ class GrammarTests(unittest.TestCase):
|
||||
### testlist: test (',' test)* [',']
|
||||
# These have been exercised enough above
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
'''
|
||||
def test_classdef(self):
|
||||
# 'class' NAME ['(' [testlist] ')'] ':' suite
|
||||
class B: pass
|
||||
@@ -1542,13 +1637,28 @@ class GrammarTests(unittest.TestCase):
|
||||
def meth2(self, arg): pass
|
||||
def meth3(self, a1, a2): pass
|
||||
|
||||
# decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
||||
# decorator: '@' namedexpr_test NEWLINE
|
||||
# decorators: decorator+
|
||||
# decorated: decorators (classdef | funcdef)
|
||||
def class_decorator(x): return x
|
||||
@class_decorator
|
||||
class G: pass
|
||||
|
||||
# Test expressions as decorators (PEP 614):
|
||||
@False or class_decorator
|
||||
class H: pass
|
||||
@d := class_decorator
|
||||
class I: pass
|
||||
@lambda c: class_decorator(c)
|
||||
class J: pass
|
||||
@[..., class_decorator, ...][1]
|
||||
class K: pass
|
||||
@class_decorator(class_decorator)(class_decorator)
|
||||
class L: pass
|
||||
@[class_decorator][0].__call__.__call__
|
||||
class M: pass
|
||||
'''
|
||||
|
||||
def test_dictcomps(self):
|
||||
# dictorsetmaker: ( (test ':' test (comp_for |
|
||||
# (',' test ':' test)* [','])) |
|
||||
@@ -1693,6 +1803,54 @@ class GrammarTests(unittest.TestCase):
|
||||
with manager() as x, manager():
|
||||
pass
|
||||
|
||||
with (
|
||||
manager()
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as x
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as (x, y),
|
||||
manager() as z,
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager(),
|
||||
manager()
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as x,
|
||||
manager() as y
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as x,
|
||||
manager()
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as x,
|
||||
manager() as y,
|
||||
manager() as z,
|
||||
):
|
||||
pass
|
||||
|
||||
with (
|
||||
manager() as x,
|
||||
manager() as y,
|
||||
manager(),
|
||||
):
|
||||
pass
|
||||
|
||||
def test_if_else_expr(self):
|
||||
# Test ifelse expressions in various cases
|
||||
def _checkeval(msg, ret):
|
||||
@@ -1815,6 +1973,18 @@ class GrammarTests(unittest.TestCase):
|
||||
with self.assertRaises(Done):
|
||||
foo().send(None)
|
||||
|
||||
def test_complex_lambda(self):
|
||||
def test1(foo, bar):
|
||||
return ""
|
||||
|
||||
def test2():
|
||||
return f"{test1(
|
||||
foo=lambda: '、、、、、、、、、、、、、、、、、',
|
||||
bar=lambda: 'abcdefghijklmnopqrstuvwxyz 123456789 123456789',
|
||||
)}"
|
||||
|
||||
self.assertEqual(test2(), "")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user