@@ -393,15 +393,21 @@ def cmd_recheck(
393393 t1 = time .time ()
394394 manager = self .fine_grained_manager .manager
395395 manager .log (f"fine-grained increment: cmd_recheck: { t1 - t0 :.3f} s" )
396- self .options .export_types = export_types
396+ old_export_types = self .options .export_types
397+ self .options .export_types = self .options .export_types or export_types
397398 if not self .following_imports ():
398- messages = self .fine_grained_increment (sources , remove , update )
399+ messages = self .fine_grained_increment (
400+ sources , remove , update , explicit_export_types = export_types
401+ )
399402 else :
400403 assert remove is None and update is None
401- messages = self .fine_grained_increment_follow_imports (sources )
404+ messages = self .fine_grained_increment_follow_imports (
405+ sources , explicit_export_types = export_types
406+ )
402407 res = self .increment_output (messages , sources , is_tty , terminal_width )
403408 self .flush_caches ()
404409 self .update_stats (res )
410+ self .options .export_types = old_export_types
405411 return res
406412
407413 def check (
@@ -412,17 +418,21 @@ def check(
412418 If is_tty is True format the output nicely with colors and summary line
413419 (unless disabled in self.options). Also pass the terminal_width to formatter.
414420 """
415- self .options .export_types = export_types
421+ old_export_types = self .options .export_types
422+ self .options .export_types = self .options .export_types or export_types
416423 if not self .fine_grained_manager :
417424 res = self .initialize_fine_grained (sources , is_tty , terminal_width )
418425 else :
419426 if not self .following_imports ():
420- messages = self .fine_grained_increment (sources )
427+ messages = self .fine_grained_increment (sources , explicit_export_types = export_types )
421428 else :
422- messages = self .fine_grained_increment_follow_imports (sources )
429+ messages = self .fine_grained_increment_follow_imports (
430+ sources , explicit_export_types = export_types
431+ )
423432 res = self .increment_output (messages , sources , is_tty , terminal_width )
424433 self .flush_caches ()
425434 self .update_stats (res )
435+ self .options .export_types = old_export_types
426436 return res
427437
428438 def flush_caches (self ) -> None :
@@ -535,6 +545,7 @@ def fine_grained_increment(
535545 sources : list [BuildSource ],
536546 remove : list [str ] | None = None ,
537547 update : list [str ] | None = None ,
548+ explicit_export_types : bool = False ,
538549 ) -> list [str ]:
539550 """Perform a fine-grained type checking increment.
540551
@@ -545,6 +556,8 @@ def fine_grained_increment(
545556 sources: sources passed on the command line
546557 remove: paths of files that have been removed
547558 update: paths of files that have been changed or created
559+ explicit_export_types: --export-type was passed in a check command
560+ (as opposite to being set in dmypy start)
548561 """
549562 assert self .fine_grained_manager is not None
550563 manager = self .fine_grained_manager .manager
@@ -559,6 +572,10 @@ def fine_grained_increment(
559572 # Use the remove/update lists to update fswatcher.
560573 # This avoids calling stat() for unchanged files.
561574 changed , removed = self .update_changed (sources , remove or [], update or [])
575+ if explicit_export_types :
576+ # If --export-types is given, we need to force full re-checking of all
577+ # explicitly passed files, since we need to visit each expression.
578+ add_all_sources_to_changed (sources , changed )
562579 changed += self .find_added_suppressed (
563580 self .fine_grained_manager .graph , set (), manager .search_paths
564581 )
@@ -577,7 +594,9 @@ def fine_grained_increment(
577594 self .previous_sources = sources
578595 return messages
579596
580- def fine_grained_increment_follow_imports (self , sources : list [BuildSource ]) -> list [str ]:
597+ def fine_grained_increment_follow_imports (
598+ self , sources : list [BuildSource ], explicit_export_types : bool = False
599+ ) -> list [str ]:
581600 """Like fine_grained_increment, but follow imports."""
582601 t0 = time .time ()
583602
@@ -603,6 +622,9 @@ def fine_grained_increment_follow_imports(self, sources: list[BuildSource]) -> l
603622 changed , new_files = self .find_reachable_changed_modules (
604623 sources , graph , seen , changed_paths
605624 )
625+ if explicit_export_types :
626+ # Same as in fine_grained_increment().
627+ add_all_sources_to_changed (sources , changed )
606628 sources .extend (new_files )
607629
608630 # Process changes directly reachable from roots.
@@ -1011,6 +1033,22 @@ def find_all_sources_in_build(
10111033 return result
10121034
10131035
1036+ def add_all_sources_to_changed (sources : list [BuildSource ], changed : list [tuple [str , str ]]) -> None :
1037+ """Add all (explicit) sources to the list changed files in place.
1038+
1039+ Use this when re-processing of unchanged files is needed (e.g. for
1040+ the purpose of exporting types for inspections).
1041+ """
1042+ changed_set = set (changed )
1043+ changed .extend (
1044+ [
1045+ (bs .module , bs .path )
1046+ for bs in sources
1047+ if bs .path and (bs .module , bs .path ) not in changed_set
1048+ ]
1049+ )
1050+
1051+
10141052def fix_module_deps (graph : mypy .build .Graph ) -> None :
10151053 """After an incremental update, update module dependencies to reflect the new state.
10161054
0 commit comments