const { writeFile , readFile , unlink } = require ( "fs" ) ; const tmp = require ( "tmp" ) ; const { callback } = require ( "awaiting" ) ; const { spawn } = require ( "child_process" ) ; interface ParserOptions { parser ? : string ; tabWidth ? : number ; useTabs ? : boolean ; util ? : string ; } function close ( proc , cb ) { proc . on ( "close" , ( code ) => cb ( undefined , code ) ) ; } function yapf ( input_path ) { return spawn ( "yapf" , [ "-i" , input_path ] ) ; } function tail ( str ? , lines = 4 ) { if ( str == null ) { return "Problem running formatter." ; } else { return ( str . trim ( ) . split ( /\r?\n/ ) . slice ( - lines ) . filter ( ( x ) => x . trim ( ) . length > 0 ) . join ( "\n" ) || "" ) ; } } export async function python_format ( input , options , logger ) { const input_path = await callback ( tmp . file ) ; try { await callback ( writeFile , input_path , input ) ; const util = options . util || "yapf" ; if ( util !== "yapf" ) { throw new Error ( "This project only supports 'yapf' for formatting Python" ) ; } const py_formatter = yapf ( input_path ) ; py_formatter . on ( "error" , ( err ) => { logger . debug ( `Formatting utility exited with error no ${ ( err as any ) . errno }` ) ; } ) ; let stdout = "" ; let stderr = "" ; py_formatter . stdout . on ( "data" , ( data ) => ( stdout += data . toString ( ) ) ) ; py_formatter . stderr . on ( "data" , ( data ) => ( stderr += data . toString ( ) ) ) ; const code = await callback ( close , py_formatter ) ; if ( code ) { if ( code === - 2 ) { throw new Error ( `Formatting utility "${ util }" is not installed` ) ; } stderr = tail ( stderr ) ; const err_msg = `Python formatter "${ util }" exited with code ${ code }:\n${ stdout }\n${ stderr }` ; logger . debug ( `format python error: ${ err_msg }` ) ; throw new Error ( err_msg ) ; } const output = await callback ( readFile , input_path ) ; const s = output . toString ( "utf-8" ) ; return s ; } finally { unlink ( input_path , ( ) => { } ) ; } }