| |
| |
|
|
| """ |
| Uses TreeFragment to test invalid syntax. |
| """ |
|
|
|
|
| import ast |
| import textwrap |
|
|
| from ...TestUtils import CythonTest |
| from .. import ExprNodes |
| from ..Errors import CompileError |
|
|
| |
| 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.5j', |
| '1_00_00.5e5', |
| '1_00_00j', |
| '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 = [ |
| |
| '0_', |
| '42_', |
| '1.4j_', |
| '0x_', |
| '0b1_', |
| '0xf_', |
| '0o5_', |
| '0 if 1_Else 1', |
| |
| '0_b0', |
| '0_xf', |
| '0_o5', |
| |
| |
| '0_7', |
| '09_99', |
| |
| '4_______2', |
| '0.1__4', |
| '0.1__4j', |
| '0b1001__0100', |
| '0xffff__ffff', |
| '0x___', |
| '0o5__77', |
| '1e1__0', |
| '1e1__0j', |
| |
| '1_.4', |
| '1_.4j', |
| |
| '1._4', |
| '1._4j', |
| '._5', |
| '._5j', |
| |
| '1.0e+_1', |
| '1.0e+_1j', |
| |
| '1.4_j', |
| '1.4e5_j', |
| |
| '1_e1', |
| '1.4_e1', |
| '1.4_e1j', |
| |
| '1e_1', |
| '1.4e_1', |
| '1.4e_1j', |
| |
| '(1+1.5_j_)', |
| '(1+1.5_j)', |
| |
| '1_ 2', |
| '1 _2', |
| '1_2.2_ 1', |
| '1_2.2 _1', |
| '1_2e _1', |
| '1_2e2 _1', |
| '1_2e 2_1', |
| ] |
|
|
|
|
| INVALID_ELLIPSIS = [ |
| (". . .", 2, 0), |
| (". ..", 2, 0), |
| (".. .", 2, 0), |
| (". ...", 2, 0), |
| (". ... .", 2, 0), |
| (".. ... .", 2, 0), |
| (". ... ..", 2, 0), |
| (""" |
| ( |
| . |
| .. |
| ) |
| """, 3, 4), |
| (""" |
| [ |
| .. |
| ., |
| None |
| ] |
| """, 3, 4), |
| (""" |
| { |
| None, |
| . |
| . |
| |
| . |
| } |
| """, 4, 4) |
| ] |
|
|
|
|
| class TestGrammar(CythonTest): |
|
|
| def test_invalid_number_literals(self): |
| for literal in INVALID_UNDERSCORE_LITERALS: |
| for expression in ['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']: |
| code = 'x = ' + expression % literal |
| try: |
| self.fragment('''\ |
| # cython: language_level=3 |
| ''' + code) |
| except CompileError as exc: |
| assert code in [s.strip() for s in str(exc).splitlines()], str(exc) |
| else: |
| assert False, "Invalid Cython code '%s' failed to raise an exception" % code |
|
|
| def test_valid_number_literals(self): |
| for literal in VALID_UNDERSCORE_LITERALS: |
| for i, expression in enumerate(['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']): |
| code = 'x = ' + expression % literal |
| node = self.fragment('''\ |
| # cython: language_level=3 |
| ''' + code).root |
| assert node is not None |
|
|
| literal_node = node.stats[0].rhs |
| if i > 0: |
| |
| literal_node = literal_node.operand2 if i % 2 else literal_node.operand1 |
| if 'j' in literal or 'J' in literal: |
| if '+' in literal: |
| |
| assert isinstance(literal_node, ExprNodes.AddNode), (literal, literal_node) |
| else: |
| assert isinstance(literal_node, ExprNodes.ImagNode), (literal, literal_node) |
| elif '.' in literal or 'e' in literal or 'E' in literal and not ('0x' in literal or '0X' in literal): |
| assert isinstance(literal_node, ExprNodes.FloatNode), (literal, literal_node) |
| else: |
| assert isinstance(literal_node, ExprNodes.IntNode), (literal, literal_node) |
|
|
| def test_invalid_ellipsis(self): |
| ERR = ":{0}:{1}: Expected an identifier or literal" |
| for code, line, col in INVALID_ELLIPSIS: |
| try: |
| ast.parse(textwrap.dedent(code)) |
| except SyntaxError as exc: |
| assert True |
| else: |
| assert False, "Invalid Python code '%s' failed to raise an exception" % code |
|
|
| try: |
| self.fragment('''\ |
| # cython: language_level=3 |
| ''' + code) |
| except CompileError as exc: |
| assert ERR.format(line, col) in str(exc), str(exc) |
| else: |
| assert False, "Invalid Cython code '%s' failed to raise an exception" % code |
|
|
|
|
| if __name__ == "__main__": |
| import unittest |
| unittest.main() |
|
|