mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
commented and cleaned up
This commit is contained in:
1 parent
ddd8151792
commit
2a172a6fa1
2 files changed
+41
-115
No files matched your search
@@ -6,120 +6,116 @@ GLOBAL_VAR = None
|
||||
|
||||
class NamedExpressionInvalidTest(unittest.TestCase):
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_01(self):
|
||||
code = """x := 0"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_02(self):
|
||||
code = """x = y := 0"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_03(self):
|
||||
code = """y := f(x)"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_04(self):
|
||||
code = """y0 = y1 := f(x)"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_06(self):
|
||||
code = """((a, b) := (1, 2))"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "cannot use assignment expressions with tuple"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_07(self):
|
||||
code = """def spam(a = b := 42): pass"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_08(self):
|
||||
code = """def spam(a: b := 42 = 5): pass"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_09(self):
|
||||
code = """spam(a=b := 'c')"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_10(self):
|
||||
code = """spam(x = y := f(x))"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_11(self):
|
||||
code = """spam(a=1, b := 2)"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError,
|
||||
# "positional argument follows keyword argument"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_12(self):
|
||||
code = """spam(a=1, (b := 2))"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError,
|
||||
# "positional argument follows keyword argument"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_13(self):
|
||||
code = """spam(a=1, (b := 2))"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError,
|
||||
# "positional argument follows keyword argument"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_14(self):
|
||||
code = """(x := lambda: y := 1)"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_15(self):
|
||||
code = """(lambda: x := 1)"""
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError,
|
||||
# "cannot use assignment expressions with lambda"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_16(self):
|
||||
code = "[i + 1 for i in i := [1,2]]"
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_17(self):
|
||||
code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"
|
||||
|
||||
#with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
|
||||
with self.assertRaises(SyntaxError): # TODO RustPython
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
def test_named_expression_invalid_in_class_body(self):
|
||||
@@ -131,6 +127,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
|
||||
"assignment expression within a comprehension cannot be used in a class body"):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_rebinding_comprehension_iteration_variable(self):
|
||||
cases = [
|
||||
("Local reuse", 'i', "[i := 0 for i in range(5)]"),
|
||||
@@ -143,18 +140,17 @@ class NamedExpressionInvalidTest(unittest.TestCase):
|
||||
"[(i, j) for i in range(5) for j in range(5) if True or (i:=10)]"),
|
||||
]
|
||||
for case, target, code in cases:
|
||||
msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
|
||||
with self.subTest(case=case):
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}, {})
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_rebinding_comprehension_inner_loop(self):
|
||||
cases = [
|
||||
("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"),
|
||||
("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"),
|
||||
]
|
||||
for case, target, code in cases:
|
||||
#msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
|
||||
with self.subTest(case=case):
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(code, {}) # Module scope
|
||||
@@ -163,6 +159,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
|
||||
with self.assertRaises(SyntaxError):
|
||||
exec(f"lambda: {code}", {}) # Function scope
|
||||
|
||||
# Test modified to accept syntax error with deviating message
|
||||
def test_named_expression_invalid_comprehension_iterable_expression(self):
|
||||
cases = [
|
||||
("Top level", "[i for i in (i := range(5))]"),
|
||||
@@ -175,7 +172,6 @@ class NamedExpressionInvalidTest(unittest.TestCase):
|
||||
("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"),
|
||||
("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"),
|
||||
]
|
||||
#msg = "assignment expression cannot be used in a comprehension iterable expression"
|
||||
for case, code in cases:
|
||||
with self.subTest(case=case):
|
||||
with self.assertRaises(SyntaxError):
|
||||
@@ -339,10 +335,10 @@ print(a)"""
|
||||
self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])
|
||||
self.assertEqual(y, 3)
|
||||
|
||||
# TODO RustPython,
|
||||
@unittest.expectedFailure # TODO RustPython
|
||||
# TODO RustPython, added test_named_expression_scope_06_rp_modified as
|
||||
# minimaly modified variant of this test.
|
||||
@unittest.expectedFailure
|
||||
def test_named_expression_scope_06(self):
|
||||
#spam=1000
|
||||
res = [[spam := i for i in range(3)] for j in range(2)]
|
||||
|
||||
self.assertEqual(res, [[0, 1, 2], [0, 1, 2]])
|
||||
@@ -388,7 +384,7 @@ print(a)"""
|
||||
self.assertEqual(res, [0, 2])
|
||||
self.assertEqual(a, 2)
|
||||
|
||||
# TODO RustPython,
|
||||
# TODO RustPython, added test_named_expression_scope_10_rp_modified
|
||||
@unittest.expectedFailure
|
||||
def test_named_expression_scope_10(self):
|
||||
res = [b := [a := 1 for i in range(2)] for j in range(2)]
|
||||
|
||||
@@ -271,74 +271,6 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
/*let mut handled=false;
|
||||
if curr_st_typ == SymbolTableType::Comprehension
|
||||
{
|
||||
if symbol.is_assign_namedexpr_in_comprehension {
|
||||
// propagate symbol to next higher level that can hold it,
|
||||
// i.e., function or module. Comprehension is skipped and
|
||||
// Class is not allowed and detected as error.
|
||||
//symbol.scope = SymbolScope::Nonlocal;
|
||||
handled = true;
|
||||
self.analyze_symbol_comprehension(symbol, 0)?
|
||||
}
|
||||
if symbol.is_iter {
|
||||
if let Some(parent_symbol) = self.tables.last().unwrap().0.get(&symbol.name) {
|
||||
if parent_symbol.is_assigned {
|
||||
return Err(SymbolTableError {
|
||||
error: format!("assignment expression cannot rebind comprehension iteration variable {}", symbol.name),
|
||||
location: Default::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !handled {
|
||||
match symbol.scope {
|
||||
SymbolScope::Nonlocal => {
|
||||
let scope_depth = self.tables.len();
|
||||
if scope_depth > 0 {
|
||||
// check if the name is already defined in any outer scope
|
||||
// therefore
|
||||
if scope_depth < 2
|
||||
|| !self
|
||||
.tables
|
||||
.iter()
|
||||
.skip(1) // omit the global scope as it is not non-local
|
||||
.rev() // revert the order for better performance
|
||||
.any(|t| t.0.contains_key(&symbol.name))
|
||||
// true when any of symbol tables contains the name -> then negate
|
||||
{
|
||||
return Err(SymbolTableError {
|
||||
error: format!("no binding for nonlocal '{}' found", symbol.name),
|
||||
location: Default::default(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(SymbolTableError {
|
||||
error: format!(
|
||||
"nonlocal {} defined at place without an enclosing scope",
|
||||
symbol.name
|
||||
),
|
||||
location: Default::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
SymbolScope::Global => {
|
||||
// TODO: add more checks for globals?
|
||||
}
|
||||
SymbolScope::Local => {
|
||||
// all is well
|
||||
}
|
||||
SymbolScope::Unknown => {
|
||||
// Try hard to figure out what the scope of this symbol is.
|
||||
self.analyze_unknown_symbol(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())*/
|
||||
}
|
||||
|
||||
fn analyze_unknown_symbol(&self, symbol: &mut Symbol) {
|
||||
@@ -381,9 +313,7 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
||||
let table_type = last.1;
|
||||
|
||||
// it is not allowed to use an iterator variable as assignee in a named expression
|
||||
if
|
||||
/*symbol.is_assign_namedexpr_in_comprehension && (maybe this could be asserted) */
|
||||
symbol.is_iter {
|
||||
if symbol.is_iter {
|
||||
return Err(SymbolTableError {
|
||||
error: format!(
|
||||
"assignment expression cannot rebind comprehension iteration variable {}",
|
||||
@@ -903,7 +833,7 @@ impl SymbolTableBuilder {
|
||||
// named expressions are not allowed in the definiton of
|
||||
// comprehension iterator definitions
|
||||
if let ExpressionContext::IterDefinitionExp = *context {
|
||||
return Err(SymbolTableError {
|
||||
return Err(SymbolTableError {
|
||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_string(),
|
||||
location: Default::default(),
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user