Lichen

pyparser/test/test_pyparse.py

961:d1fe5052f956
2021-11-14 Paul Boddie Introduced copyable and mutable flags in the tagged region of attribute values. Such flags are set when new integer and floating point values are created, but the mutable flag is cleared when such attributes are propagated between functions in order to prevent values being replaced upon assignment to parameter names, this being a concern when value copying is introduced. tagged-address-values
     1 # -*- coding: utf-8 -*-     2 import py     3 from pyparser import pyparse     4 from pyparser.pygram import syms     5 from pyparser.error import SyntaxError, IndentationError     6 from pyparser import consts     7      8      9 class TestPythonParser:    10     11     def setup_class(self):    12         self.parser = pyparse.PythonParser()    13     14     def parse(self, source, mode="exec", info=None):    15         if info is None:    16             info = pyparse.CompileInfo("<test>", mode)    17         return self.parser.parse_source(source, info)    18     19     def test_with_and_as(self):    20         py.test.raises(SyntaxError, self.parse, "with = 23")    21         py.test.raises(SyntaxError, self.parse, "as = 2")    22     23     def test_dont_imply_dedent(self):    24         info = pyparse.CompileInfo("<test>", "single",    25                                    consts.PyCF_DONT_IMPLY_DEDENT)    26         self.parse('if 1:\n  x\n', info=info)    27         self.parse('x = 5 ', info=info)    28     29     def test_clear_state(self):    30         assert self.parser.root is None    31         tree = self.parse("name = 32")    32         assert self.parser.root is None    33     34     def test_encoding(self):    35         info = pyparse.CompileInfo("<test>", "exec")    36         tree = self.parse("""# coding: latin-1    37 stuff = "nothing"    38 """, info=info)    39         assert tree.type == syms["encoding_decl"]    40         assert tree.encoding == "iso-8859-1"    41         assert info.encoding == "iso-8859-1"    42         sentence = u"u'Die M??nner ??rgen sich!'"    43         input = (u"# coding: utf-7\nstuff = %s" % (sentence,)).encode("utf-7")    44         tree = self.parse(input, info=info)    45         assert info.encoding == "utf-7"    46         input = "# coding: iso-8859-15\nx"    47         self.parse(input, info=info)    48         assert info.encoding == "iso-8859-15"    49         input = "\xEF\xBB\xBF# coding: utf-8\nx"    50         self.parse(input, info=info)    51         assert info.encoding == "utf-8"    52         input = "# coding: utf-8\nx"    53         info.flags |= consts.PyCF_SOURCE_IS_UTF8    54         exc = py.test.raises(SyntaxError, self.parse, input, info=info).value    55         info.flags &= ~consts.PyCF_SOURCE_IS_UTF8    56         assert exc.msg == "coding declaration in unicode string"    57         input = "\xEF\xBB\xBF# coding: latin-1\nx"    58         exc = py.test.raises(SyntaxError, self.parse, input).value    59         assert exc.msg == "UTF-8 BOM with latin-1 coding cookie"    60         input = "# coding: not-here"    61         exc = py.test.raises(SyntaxError, self.parse, input).value    62         assert exc.msg == "Unknown encoding: not-here"    63         input = u"# coding: ascii\n\xe2".encode('utf-8')    64         exc = py.test.raises(SyntaxError, self.parse, input).value    65         assert exc.msg == ("'ascii' codec can't decode byte 0xc3 "    66                            "in position 16: ordinal not in range(128)")    67     68     def test_non_unicode_codec(self):    69         exc = py.test.raises(SyntaxError, self.parse, """\    70 # coding: string-escape    71 \x70\x72\x69\x6e\x74\x20\x32\x2b\x32\x0a    72 """).value    73         assert exc.msg == "codec did not return a unicode object"    74     75     def test_syntax_error(self):    76         parse = self.parse    77         exc = py.test.raises(SyntaxError, parse, "name another for").value    78         assert exc.msg == "invalid syntax"    79         assert exc.lineno == 1    80         assert exc.offset == 5    81         assert exc.text.startswith("name another for")    82         exc = py.test.raises(SyntaxError, parse, "x = \"blah\n\n\n").value    83         assert exc.msg == "EOL while scanning string literal"    84         assert exc.lineno == 1    85         assert exc.offset == 5    86         exc = py.test.raises(SyntaxError, parse, "x = '''\n\n\n").value    87         assert exc.msg == "EOF while scanning triple-quoted string literal"    88         assert exc.lineno == 1    89         assert exc.offset == 5    90         assert exc.lastlineno == 3    91         for input in ("())", "(()", "((", "))"):    92             py.test.raises(SyntaxError, parse, input)    93         exc = py.test.raises(SyntaxError, parse, "x = (\n\n(),\n(),").value    94         assert exc.msg == "parenthesis is never closed"    95         assert exc.lineno == 1    96         assert exc.offset == 5    97         assert exc.lastlineno == 5    98         exc = py.test.raises(SyntaxError, parse, "abc)").value    99         assert exc.msg == "unmatched ')'"   100         assert exc.lineno == 1   101         assert exc.offset == 4   102    103     def test_is(self):   104         self.parse("x is y")   105         self.parse("x is not y")   106    107     def test_indentation_error(self):   108         parse = self.parse   109         input = """   110 def f():   111 pass"""   112         exc = py.test.raises(IndentationError, parse, input).value   113         assert exc.msg == "expected an indented block"   114         assert exc.lineno == 3   115         assert exc.text.startswith("pass")   116         assert exc.offset == 0   117         input = "hi\n    indented"   118         exc = py.test.raises(IndentationError, parse, input).value   119         assert exc.msg == "unexpected indent"   120         input = "def f():\n    pass\n  next_stmt"   121         exc = py.test.raises(IndentationError, parse, input).value   122         assert exc.msg == "unindent does not match any outer indentation level"   123         assert exc.lineno == 3   124    125     def test_mac_newline(self):   126         self.parse("this_is\ra_mac\rfile")   127    128     def test_mode(self):   129         assert self.parse("x = 43*54").type == syms["file_input"]   130         tree = self.parse("43**54", "eval")   131         assert tree.type == syms["eval_input"]   132         py.test.raises(SyntaxError, self.parse, "x = 54", "eval")   133         tree = self.parse("x = 43", "single")   134         assert tree.type == syms["single_input"]   135    136     def test_multiline_string(self):   137         self.parse("''' \n '''")   138         self.parse("r''' \n '''")   139    140     def test_bytes_literal(self):   141         self.parse('b" "')   142         self.parse('br" "')   143         self.parse('b""" """')   144         self.parse("b''' '''")   145         self.parse("br'\\\n'")   146    147         py.test.raises(SyntaxError, self.parse, "b'a\\n")   148    149     def test_new_octal_literal(self):   150         self.parse('0777')   151         self.parse('0o777')   152         self.parse('0o777L')   153         py.test.raises(SyntaxError, self.parse, "0o778")   154    155     def test_new_binary_literal(self):   156         self.parse('0b1101')   157         self.parse('0b0l')   158         py.test.raises(SyntaxError, self.parse, "0b112")   159    160     def test_universal_newlines(self):   161         fmt = 'stuff = """hello%sworld"""'   162         expected_tree = self.parse(fmt % '\n')   163         for linefeed in ["\r\n","\r"]:   164             tree = self.parse(fmt % linefeed)   165             assert expected_tree == tree