22import dataclasses
33import inspect
44import subprocess
5+ import textwrap
56import typing
67
78from .errors import CxxParseError
89from .preprocessor import make_pcpp_preprocessor
910from .options import ParserOptions
10- from .simple import parse_string , ParsedData
11+ from .simple import parse_string , parse_typename , ParsedData
1112
1213
13- def nondefault_repr (data : ParsedData ) -> str :
14+ def nondefault_repr (data : typing . Any ) -> str :
1415 """
1516 Similar to the default dataclass repr, but exclude any
1617 default parameters or parameters with compare=False
@@ -50,7 +51,13 @@ def _inner_repr(o: typing.Any) -> str:
5051
5152
5253def gentest (
53- infile : str , name : str , outfile : str , verbose : bool , fail : bool , pcpp : bool
54+ infile : str ,
55+ name : str ,
56+ outfile : str ,
57+ verbose : bool ,
58+ fail : bool ,
59+ pcpp : bool ,
60+ typename_mode : bool ,
5461) -> None :
5562 # Goal is to allow making a unit test as easy as running this dumper
5663 # on a file and copy/pasting this into a test
@@ -67,46 +74,76 @@ def gentest(
6774 maybe_options = "options = ParserOptions(preprocessor=make_pcpp_preprocessor())"
6875 popt = ", options=options"
6976
70- try :
71- data = parse_string (content , options = options )
72- if fail :
73- raise ValueError ("did not fail" )
74- except CxxParseError :
75- if not fail :
76- raise
77- # do it again, but strip the content so the error message matches
77+ if typename_mode :
7878 try :
79- parse_string (content .strip (), options = options )
80- except CxxParseError as e2 :
81- err = str (e2 )
82-
83- if not fail :
84- stmt = nondefault_repr (data )
85- stmt = f"""
86- { maybe_options }
87- data = parse_string(content, cleandoc=True{ popt } )
88-
89- assert data == { stmt }
90- """
79+ dtype = parse_typename (content .strip (), options = options )
80+ if fail :
81+ raise ValueError ("did not fail" )
82+ except CxxParseError :
83+ if not fail :
84+ raise
85+ try :
86+ parse_typename (content .strip (), options = options )
87+ except CxxParseError as e2 :
88+ err = str (e2 )
89+
90+ if not fail :
91+ stmt = nondefault_repr (dtype )
92+ stmt = f"""
93+ { maybe_options }
94+ dtype = parse_typename(content.strip(){ popt } )
95+
96+ assert dtype == { stmt }
97+ """
98+ else :
99+ stmt = f"""
100+ { maybe_options }
101+ err = { repr (err )}
102+ with pytest.raises(CxxParseError, match=re.escape(err)):
103+ parse_typename(content.strip(){ popt } )
104+ """
91105 else :
92- stmt = f"""
93- { maybe_options }
94- err = { repr (err )}
95- with pytest.raises(CxxParseError, match=re.escape(err)):
96- parse_string(content, cleandoc=True{ popt } )
97- """
98-
99- content = ("\n " + content .strip ()).replace ("\n " , "\n " )
100- content = "\n " .join (l .rstrip () for l in content .splitlines ())
106+ try :
107+ data = parse_string (content , options = options )
108+ if fail :
109+ raise ValueError ("did not fail" )
110+ except CxxParseError :
111+ if not fail :
112+ raise
113+ # do it again, but strip the content so the error message matches
114+ try :
115+ parse_string (content .strip (), options = options )
116+ except CxxParseError as e2 :
117+ err = str (e2 )
118+
119+ if not fail :
120+ stmt = nondefault_repr (data )
121+ stmt = f"""
122+ { maybe_options }
123+ data = parse_string(content, cleandoc=True{ popt } )
101124
102- stmt = inspect .cleandoc (
103- f'''
104- def test_{ name } () -> None:
105- content = """{ content }
125+ assert data == { stmt }
106126 """
107- { stmt .strip ()}
108- '''
109- )
127+ else :
128+ stmt = f"""
129+ { maybe_options }
130+ err = { repr (err )}
131+ with pytest.raises(CxxParseError, match=re.escape(err)):
132+ parse_string(content, cleandoc=True{ popt } )
133+ """
134+
135+ stmt = textwrap .dedent (stmt ).strip ()
136+ stmt = textwrap .indent (stmt , " " * 4 )
137+ content = inspect .cleandoc (content )
138+ content = textwrap .indent ("\n " + content , " " * 8 )
139+ content = "\n " .join (l .rstrip () for l in content .splitlines ())
140+
141+ stmt = f"""def test_{ name } () -> None:
142+ content = \" \" \" { content }
143+ \" \" \"
144+
145+ { stmt }
146+ """
110147
111148 # format it with black
112149 stmt = subprocess .check_output (
@@ -125,11 +162,26 @@ def test_{name}() -> None:
125162 parser .add_argument ("header" )
126163 parser .add_argument ("name" , nargs = "?" , default = "TODO" )
127164 parser .add_argument ("--pcpp" , default = False , action = "store_true" )
165+ parser .add_argument (
166+ "--typename" ,
167+ dest = "typename_mode" ,
168+ default = False ,
169+ action = "store_true" ,
170+ help = "Generate tests for parse_typename" ,
171+ )
128172 parser .add_argument ("-v" , "--verbose" , default = False , action = "store_true" )
129173 parser .add_argument ("-o" , "--output" , default = "-" )
130174 parser .add_argument (
131175 "-x" , "--fail" , default = False , action = "store_true" , help = "Expect failure"
132176 )
133177 args = parser .parse_args ()
134178
135- gentest (args .header , args .name , args .output , args .verbose , args .fail , args .pcpp )
179+ gentest (
180+ args .header ,
181+ args .name ,
182+ args .output ,
183+ args .verbose ,
184+ args .fail ,
185+ args .pcpp ,
186+ args .typename_mode ,
187+ )
0 commit comments