@@ -293,6 +293,56 @@ def src_info(self) -> Dict[str, Any]:
293293 get_logger ().debug (e )
294294 return result
295295
296+ def format_model (
297+ self , save : bool = False , canonicalize : Union [bool , List [str ]] = False
298+ ) -> None :
299+ """
300+ Run stanc's auto-formatter on the model code. Either saves directly
301+ back to the file or prints for inspection
302+
303+
304+ :param save: If True, save the updated code to disk, rather than
305+ printing it. By default False
306+ :param canonicalize: Whether or not the compiler should 'canonicalize'
307+ the Stan model, removing things like deprecated syntax. Default is
308+ False. If True, all canonicalizations are run. If it is a list of
309+ strings, those options are passed to stanc (new in Stan 2.29)
310+ """
311+ if self .stan_file is None or not os .path .isfile (self .stan_file ):
312+ raise ValueError ("No Stan file found for this module" )
313+ try :
314+ cmd = [
315+ os .path .join ('.' , 'bin' , 'stanc' + EXTENSION ),
316+ '--auto-format' ,
317+ ]
318+ if canonicalize :
319+ if isinstance (canonicalize , list ):
320+ cmd .append ('--canonicalize=' + ',' .join (canonicalize ))
321+ else :
322+ cmd .append ('--print-canonical' )
323+
324+ cmd .append (self .stan_file )
325+
326+ out = subprocess .run (
327+ cmd ,
328+ cwd = cmdstan_path (),
329+ capture_output = True ,
330+ text = True ,
331+ check = True ,
332+ )
333+ if out .stderr :
334+ print (out .stderr )
335+ result = out .stdout
336+ if save :
337+ shutil .copyfile (self .stan_file , self .stan_file + '.bak' )
338+ with (open (self .stan_file , 'w' )) as file :
339+ file .write (result )
340+ else :
341+ print (result )
342+
343+ except (ValueError , RuntimeError ) as e :
344+ raise RuntimeError ("Stanc formatting failed" ) from e
345+
296346 @property
297347 def stanc_options (self ) -> Dict [str , Union [bool , int , str ]]:
298348 """Options to stanc compilers."""
0 commit comments