88import platform
99import shutil
1010import subprocess
11- from copy import copy
1211from datetime import datetime
1312from pathlib import Path
1413from typing import Any , Iterable , Optional , Union
3736 'warn-pedantic' ,
3837]
3938
40- # TODO(2.0): remove
41- STANC_DEPRECATED_OPTS = {
42- 'allow_undefined' : 'allow-undefined' ,
43- 'include_paths' : 'include-paths' ,
44- }
45-
4639STANC_IGNORE_OPTS = [
4740 'debug-lex' ,
4841 'debug-parse' ,
6760OptionalPath = Union [str , os .PathLike , None ]
6861
6962
70- # TODO(2.0): can remove add function and other logic
7163class CompilerOptions :
7264 """
7365 User-specified flags for stanc and C++ compiler.
@@ -95,26 +87,6 @@ def __repr__(self) -> str:
9587 self ._stanc_options , self ._cpp_options
9688 )
9789
98- def __eq__ (self , other : Any ) -> bool :
99- """Overrides the default implementation"""
100- if self .is_empty () and other is None : # equiv w/r/t compiler
101- return True
102- if not isinstance (other , CompilerOptions ):
103- return False
104- return (
105- self ._stanc_options == other .stanc_options
106- and self ._cpp_options == other .cpp_options
107- and self ._user_header == other .user_header
108- )
109-
110- def is_empty (self ) -> bool :
111- """True if no options specified."""
112- return (
113- self ._stanc_options == {}
114- and self ._cpp_options == {}
115- and self ._user_header == ''
116- )
117-
11890 @property
11991 def stanc_options (self ) -> dict [str , Union [bool , int , str , Iterable [str ]]]:
12092 """Stanc compiler options."""
@@ -144,31 +116,12 @@ def validate_stanc_opts(self) -> None:
144116 Check stanc compiler args and consistency between stanc and C++ options.
145117 Raise ValueError if bad config is found.
146118 """
147- # pylint: disable=no-member
148119 if self ._stanc_options is None :
149120 return
150121 ignore = []
151122 paths = None
152123 has_o_flag = False
153124
154- for deprecated , replacement in STANC_DEPRECATED_OPTS .items ():
155- if deprecated in self ._stanc_options :
156- if replacement :
157- get_logger ().warning (
158- 'compiler option "%s" is deprecated, use "%s" instead' ,
159- deprecated ,
160- replacement ,
161- )
162- self ._stanc_options [replacement ] = copy (
163- self ._stanc_options [deprecated ]
164- )
165- del self ._stanc_options [deprecated ]
166- else :
167- get_logger ().warning (
168- 'compiler option "%s" is deprecated and should '
169- 'not be used' ,
170- deprecated ,
171- )
172125 for key , val in self ._stanc_options .items ():
173126 if key in STANC_IGNORE_OPTS :
174127 get_logger ().info ('ignoring compiler option: %s' , key )
@@ -267,37 +220,6 @@ def validate_user_header(self) -> None:
267220
268221 self ._cpp_options ['USER_HEADER' ] = self ._user_header
269222
270- def add (self , new_opts : "CompilerOptions" ) -> None : # noqa: disable=Q000
271- """Adds options to existing set of compiler options."""
272- if new_opts .stanc_options is not None :
273- if self ._stanc_options is None :
274- self ._stanc_options = new_opts .stanc_options
275- else :
276- for key , val in new_opts .stanc_options .items ():
277- if key == 'include-paths' :
278- if isinstance (val , Iterable ) and not isinstance (
279- val , str
280- ):
281- for path in val :
282- self .add_include_path (str (path ))
283- else :
284- self .add_include_path (str (val ))
285- else :
286- self ._stanc_options [key ] = val
287- if new_opts .cpp_options is not None :
288- for key , val in new_opts .cpp_options .items ():
289- self ._cpp_options [key ] = val
290- if new_opts ._user_header != '' and self ._user_header == '' :
291- self ._user_header = new_opts ._user_header
292-
293- def add_include_path (self , path : str ) -> None :
294- """Adds include path to existing set of compiler options."""
295- path = os .path .abspath (os .path .expanduser (path ))
296- if 'include-paths' not in self ._stanc_options :
297- self ._stanc_options ['include-paths' ] = [path ]
298- elif path not in self ._stanc_options ['include-paths' ]:
299- self ._stanc_options ['include-paths' ].append (path )
300-
301223 def compose_stanc (self , filename_in_msg : Optional [str ]) -> list [str ]:
302224 opts = []
303225
@@ -343,7 +265,8 @@ def compose(self, filename_in_msg: Optional[str] = None) -> list[str]:
343265
344266
345267def src_info (
346- stan_file : str , compiler_options : CompilerOptions
268+ stan_file : str ,
269+ stanc_options : Optional [dict [str , Any ]] = None ,
347270) -> dict [str , Any ]:
348271 """
349272 Get source info for Stan program file.
@@ -354,7 +277,7 @@ def src_info(
354277 cmd = (
355278 [stanc_path ()]
356279 # handle include-paths, allow-undefined etc
357- + compiler_options .compose_stanc (None )
280+ + CompilerOptions ( stanc_options = stanc_options ) .compose_stanc (None )
358281 + ['--info' , str (stan_file )]
359282 )
360283 proc = subprocess .run (cmd , capture_output = True , text = True , check = False )
@@ -407,12 +330,26 @@ def compile_stan_file(
407330 )
408331 compiler_options .validate ()
409332
333+ # if program has include directives, record path
334+ if '#include' in src .read_text ():
335+ path = os .fspath (src .parent .resolve ())
336+ if 'include-paths' not in compiler_options .stanc_options :
337+ compiler_options .stanc_options ['include-paths' ] = [path ]
338+ else :
339+ paths : list [str ] = compiler_options .stanc_options [
340+ 'include-paths'
341+ ] # type: ignore
342+ if path not in paths :
343+ paths .append (path )
344+
410345 exe_target = src .with_suffix (EXTENSION )
411346 if exe_target .exists ():
412347 exe_time = os .path .getmtime (exe_target )
413348 included_files = [src ]
414349 included_files .extend (
415- src_info (str (src ), compiler_options ).get ('included_files' , [])
350+ src_info (str (src ), compiler_options .stanc_options ).get (
351+ 'included_files' , []
352+ )
416353 )
417354 out_of_date = any (
418355 os .path .getmtime (included_file ) > exe_time
@@ -482,7 +419,7 @@ def compile_stan_file(
482419 raise ValueError (
483420 f"Failed to compile Stan model '{ src } '. Console:\n { console } "
484421 )
485- return str (exe_target )
422+ return os . fspath (exe_target )
486423
487424
488425def format_stan_file (
0 commit comments