1- """Tests for the experimental native mypy parser.
2-
3- To run these, you will need to manually install ast_serialize from
4- https://github.com/mypyc/ast_serialize first (see the README for the details).
5- """
1+ """Tests for the native mypy parser."""
62
73from __future__ import annotations
84
128import unittest
139from collections .abc import Iterator
1410
11+ import pytest
1512from librt .internal import ReadBuffer
1613
1714from mypy import defaults , nodes
2724)
2825from mypy .config_parser import parse_mypy_comments
2926from mypy .errors import CompileError
27+ from mypy .nativeparse import (
28+ State ,
29+ deserialize_imports ,
30+ native_parse ,
31+ parse_to_binary_ast ,
32+ read_statements ,
33+ )
3034from mypy .nodes import MypyFile , ParseError
3135from mypy .options import Options
3236from mypy .test .data import DataDrivenTestCase , DataSuite
3337from mypy .test .helpers import assert_string_arrays_equal
3438from mypy .util import get_mypy_comments
3539
36- # If the experimental ast_serialize module isn't installed, the following import will fail
37- # and we won't run any native parser tests.
38- try :
39- from mypy .nativeparse import (
40- State ,
41- deserialize_imports ,
42- native_parse ,
43- parse_to_binary_ast ,
44- read_statements ,
45- )
46-
47- has_nativeparse = True
48- except ImportError :
49- has_nativeparse = False
50-
5140
5241class NativeParserSuite (DataSuite ):
5342 required_out_section = True
5443 base_path = "."
55- files = (
56- ["native-parser.test" , "native-parser-python311.test" , "native-parser-python312.test" ]
57- if has_nativeparse
58- else []
59- )
44+ files = ["native-parser.test" , "native-parser-python311.test" , "native-parser-python312.test" ]
6045
6146 def run_case (self , testcase : DataDrivenTestCase ) -> None :
6247 test_parser (testcase )
@@ -65,7 +50,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
6550class NativeParserImportsSuite (DataSuite ):
6651 required_out_section = True
6752 base_path = "."
68- files = ["native-parser-imports.test" ] if has_nativeparse else []
53+ files = ["native-parser-imports.test" ]
6954
7055 def run_case (self , testcase : DataDrivenTestCase ) -> None :
7156 test_parser_imports (testcase )
@@ -238,7 +223,6 @@ def format_reachable_imports(node: MypyFile) -> list[str]:
238223 return output
239224
240225
241- @unittest .skipUnless (has_nativeparse , "nativeparse not available" )
242226class TestNativeParserBinaryFormat (unittest .TestCase ):
243227 def _assert_trivial_binary_data (self , b : bytes , / ) -> None :
244228 # A quick sanity check to ensure the serialized data looks as expected. Only covers
@@ -296,14 +280,27 @@ def test_trivial_binary_data_from_bytes_source(self) -> None:
296280 self ._assert_trivial_binary_data (b )
297281
298282 def test_invalid_bytes_raises (self ) -> None :
299- with self .assertRaises (UnicodeDecodeError ):
283+ with self .assertRaises (CompileError ):
300284 parse_to_binary_ast ("" , Options (), b"\xff " )
301285
302286
287+ class TestNativeParserCustomEncoding (unittest .TestCase ):
288+ def test_latin1 (self ) -> None :
289+ source = "# coding: latin1\n Jérôme = False"
290+ with temp_source (source , encoding = "latin1" ) as fnam :
291+ parse_to_binary_ast (fnam , Options ())
292+
293+ def test_latin1_broken (self ) -> None :
294+ source = "# coding: ascii\n Jérôme = False"
295+ with temp_source (source , encoding = "latin1" ) as fnam :
296+ with pytest .raises (UnicodeDecodeError ):
297+ parse_to_binary_ast (fnam , Options ())
298+
299+
303300@contextlib .contextmanager
304- def temp_source (text : str ) -> Iterator [str ]:
301+ def temp_source (text : str , encoding : str = "utf-8" ) -> Iterator [str ]:
305302 with tempfile .TemporaryDirectory () as temp_dir :
306303 temp_path = os .path .join (temp_dir , "t.py" )
307- with open (temp_path , "w " ) as f :
308- f .write (text )
304+ with open (temp_path , "wb " ) as f :
305+ f .write (text . encode ( encoding ) )
309306 yield temp_path
0 commit comments