@@ -10,7 +10,6 @@ import { emitCodeModel } from "./code-model.js";
1010import { saveCodeModelAsYaml } from "./external-process.js" ;
1111import { PythonEmitterOptions , PythonSdkContext , reportDiagnostic } from "./lib.js" ;
1212import { runPython3 } from "./run-python3.js" ;
13- import { disableGenerationMap , simpleTypesMap , typesMap } from "./types.js" ;
1413import { getRootNamespace , md2Rst } from "./utils.js" ;
1514
1615function addDefaultOptions ( sdkContext : PythonSdkContext ) {
@@ -59,6 +58,9 @@ async function createPythonSdkContext(
5958 return {
6059 ...sdkContext ,
6160 __endpointPathParameters : [ ] ,
61+ __typesMap : new Map ( ) ,
62+ __simpleTypesMap : new Map ( ) ,
63+ __disableGenerationMap : new Set ( ) ,
6264 } ;
6365}
6466
@@ -100,12 +102,6 @@ function walkThroughNodes(yamlMap: Record<string, any>): Record<string, any> {
100102 return yamlMap ;
101103}
102104
103- function cleanAllCache ( ) {
104- typesMap . clear ( ) ;
105- simpleTypesMap . clear ( ) ;
106- disableGenerationMap . clear ( ) ;
107- }
108-
109105export async function $onEmit ( context : EmitContext < PythonEmitterOptions > ) {
110106 try {
111107 await onEmitMain ( context ) ;
@@ -124,9 +120,6 @@ export async function $onEmit(context: EmitContext<PythonEmitterOptions>) {
124120}
125121
126122async function onEmitMain ( context : EmitContext < PythonEmitterOptions > ) {
127- // clean all cache to make sure emitter could work in watch mode
128- cleanAllCache ( ) ;
129-
130123 const program = context . program ;
131124 const sdkContext = await createPythonSdkContext ( context ) ;
132125 const root = path . join ( dirname ( fileURLToPath ( import . meta. url ) ) , ".." , ".." ) ;
@@ -168,7 +161,7 @@ async function onEmitMain(context: EmitContext<PythonEmitterOptions>) {
168161 try {
169162 await runPython3 ( path . join ( root , "/eng/scripts/setup/install.py" ) ) ;
170163 await runPython3 ( path . join ( root , "/eng/scripts/setup/prepare.py" ) ) ;
171- } catch ( error ) {
164+ } catch {
172165 // if the python env is not ready, we use pyodide instead
173166 resolvedOptions [ "use-pyodide" ] = true ;
174167 }
@@ -250,7 +243,7 @@ async function onEmitMain(context: EmitContext<PythonEmitterOptions>) {
250243 execSync (
251244 `${ venvPath } -m black --line-length=120 --quiet --fast ${ outputDir } --exclude "${ excludePattern } "` ,
252245 ) ;
253- checkForPylintIssues ( outputDir , excludePattern ) ;
246+ await checkForPylintIssues ( outputDir , excludePattern ) ;
254247 }
255248 }
256249}
@@ -269,7 +262,7 @@ async function setupPyodideCall(root: string) {
269262 if ( lockAge > 300 ) {
270263 fs . unlinkSync ( micropipLockPath ) ;
271264 }
272- } catch ( err ) {
265+ } catch {
273266 // ignore
274267 }
275268 }
@@ -288,14 +281,14 @@ async function setupPyodideCall(root: string) {
288281 fs . closeSync ( fd ) ;
289282 fs . unlinkSync ( micropipLockPath ) ;
290283 break ;
291- } catch ( err ) {
284+ } catch {
292285 await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
293286 }
294287 }
295288 return pyodide ;
296289}
297290
298- function checkForPylintIssues ( outputDir : string , excludePattern : string ) {
291+ async function checkForPylintIssues ( outputDir : string , excludePattern : string ) {
299292 const excludeRegex = new RegExp ( excludePattern ) ;
300293
301294 const shouldExcludePath = ( filePath : string ) : boolean => {
@@ -304,9 +297,8 @@ function checkForPylintIssues(outputDir: string, excludePattern: string) {
304297 return excludeRegex . test ( normalizedPath ) ;
305298 } ;
306299
307- const processFile = ( filePath : string ) => {
308- let fileContent ;
309- fileContent = fs . readFileSync ( filePath , "utf-8" ) ;
300+ const processFile = async ( filePath : string ) => {
301+ let fileContent = await fs . promises . readFile ( filePath , "utf-8" ) ;
310302 const pylintDisables : string [ ] = [ ] ;
311303 const lineEnding = fileContent . includes ( "\r\n" ) && os . platform ( ) === "win32" ? "\r\n" : "\n" ;
312304 const lines : string [ ] = fileContent . split ( lineEnding ) ;
@@ -321,32 +313,38 @@ function checkForPylintIssues(outputDir: string, excludePattern: string) {
321313 fileContent = lines [ 0 ] . includes ( "pylint: disable=" )
322314 ? [ lines [ 0 ] + "," + pylintDisables . join ( "," ) ] . concat ( lines . slice ( 1 ) ) . join ( lineEnding )
323315 : `# pylint: disable=${ pylintDisables . join ( "," ) } ${ lineEnding } ` + fileContent ;
316+ await fs . promises . writeFile ( filePath , fileContent ) ;
324317 }
325318 }
326-
327- fs . writeFileSync ( filePath , fileContent ) ;
328319 } ;
329320
330- const walkDir = ( dir : string ) => {
321+ const collectPythonFiles = async ( dir : string ) : Promise < string [ ] > => {
331322 if ( shouldExcludePath ( dir ) ) {
332- return ;
323+ return [ ] ;
333324 }
334325
335- const files = fs . readdirSync ( dir ) ;
336- files . forEach ( ( file ) => {
337- const filePath = path . join ( dir , file ) ;
326+ const entries = await fs . promises . readdir ( dir , { withFileTypes : true } ) ;
327+
328+ const promises = entries . map ( async ( entry ) => {
329+ const filePath = path . join ( dir , entry . name ) ;
338330
339331 if ( shouldExcludePath ( filePath ) ) {
340- return ;
332+ return [ ] ;
341333 }
342334
343- if ( fs . statSync ( filePath ) . isDirectory ( ) ) {
344- walkDir ( filePath ) ;
345- } else if ( file . endsWith ( ".py" ) ) {
346- processFile ( filePath ) ;
335+ if ( entry . isDirectory ( ) ) {
336+ return collectPythonFiles ( filePath ) ;
337+ } else if ( entry . name . endsWith ( ".py" ) ) {
338+ return [ filePath ] ;
347339 }
340+ return [ ] ;
348341 } ) ;
342+
343+ const results = await Promise . all ( promises ) ;
344+ return results . flat ( ) ;
349345 } ;
350346
351- walkDir ( outputDir ) ;
347+ // Collect all Python files first, then process in parallel
348+ const pythonFiles = await collectPythonFiles ( outputDir ) ;
349+ await Promise . all ( pythonFiles . map ( processFile ) ) ;
352350}
0 commit comments