|
|
|
|
|
|
| """
|
| Uses TreeFragment to test invalid syntax.
|
| """
|
|
|
| from __future__ import absolute_import
|
|
|
| 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(u'''\
|
| # 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(u'''\
|
| # 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(u'''\
|
| # 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()
|
|
|