52
52
from mypy .version import __version__
53
53
from mypy .plugin import Plugin , DefaultPlugin , ChainedPlugin
54
54
from mypy .defaults import PYTHON3_VERSION_MIN
55
+ from mypy .server .deps import get_dependencies
55
56
56
57
57
58
PYTHON_EXTENSIONS = ['.pyi' , '.py' ]
@@ -386,6 +387,7 @@ def default_lib_path(data_dir: str,
386
387
('size' , int ),
387
388
('hash' , str ),
388
389
('dependencies' , List [str ]), # names of imported modules
390
+ ('fine_grained_deps' , Dict [str , List [str ]]),
389
391
('data_mtime' , int ), # mtime of data_json
390
392
('data_json' , str ), # path of <id>.data.json
391
393
('suppressed' , List [str ]), # dependencies that weren't imported
@@ -411,6 +413,7 @@ def cache_meta_from_dict(meta: Dict[str, Any], data_json: str) -> CacheMeta:
411
413
meta .get ('size' , sentinel ),
412
414
meta .get ('hash' , sentinel ),
413
415
meta .get ('dependencies' , []),
416
+ meta .get ('fine_grained_deps' , {}),
414
417
int (meta ['data_mtime' ]) if 'data_mtime' in meta else sentinel ,
415
418
data_json ,
416
419
meta .get ('suppressed' , []),
@@ -1151,6 +1154,7 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: Optional[str],
1151
1154
'hash' : source_hash ,
1152
1155
'data_mtime' : data_mtime ,
1153
1156
'dependencies' : meta .dependencies ,
1157
+ 'fine_grained_deps' : meta .fine_grained_deps ,
1154
1158
'suppressed' : meta .suppressed ,
1155
1159
'child_modules' : meta .child_modules ,
1156
1160
'options' : (manager .options .clone_for_module (id )
@@ -1183,7 +1187,9 @@ def compute_hash(text: str) -> str:
1183
1187
1184
1188
1185
1189
def write_cache (id : str , path : str , tree : MypyFile ,
1186
- dependencies : List [str ], suppressed : List [str ],
1190
+ dependencies : List [str ],
1191
+ fine_grained_deps : Dict [str , List [str ]],
1192
+ suppressed : List [str ],
1187
1193
child_modules : List [str ], dep_prios : List [int ],
1188
1194
old_interface_hash : str , source_hash : str ,
1189
1195
ignore_all : bool , manager : BuildManager ) -> Tuple [str , Optional [CacheMeta ]]:
@@ -1278,6 +1284,7 @@ def write_cache(id: str, path: str, tree: MypyFile,
1278
1284
'hash' : source_hash ,
1279
1285
'data_mtime' : data_mtime ,
1280
1286
'dependencies' : dependencies ,
1287
+ 'fine_grained_deps' : fine_grained_deps ,
1281
1288
'suppressed' : suppressed ,
1282
1289
'child_modules' : child_modules ,
1283
1290
'options' : options .select_options_affecting_cache (),
@@ -1486,7 +1493,7 @@ class State:
1486
1493
data = None # type: Optional[str]
1487
1494
tree = None # type: Optional[MypyFile]
1488
1495
is_from_saved_cache = False # True if the tree came from the in-memory cache
1489
- dependencies = None # type: List[str] # Modules directly imported by the module
1496
+ dependencies = None # type: List[str]
1490
1497
suppressed = None # type: List[str] # Suppressed/missing dependencies
1491
1498
priorities = None # type: Dict[str, int]
1492
1499
@@ -1523,6 +1530,8 @@ class State:
1523
1530
# Whether the module has an error or any of its dependencies have one.
1524
1531
transitive_error = False
1525
1532
1533
+ fine_grained_deps = None # type: Dict[str, Set[str]]
1534
+
1526
1535
# Type checker used for checking this file. Use type_checker() for
1527
1536
# access and to construct this on demand.
1528
1537
_type_checker = None # type: Optional[TypeChecker]
@@ -1622,6 +1631,7 @@ def __init__(self,
1622
1631
# Make copies, since we may modify these and want to
1623
1632
# compare them to the originals later.
1624
1633
self .dependencies = list (self .meta .dependencies )
1634
+ self .fine_grained_deps = {k : set (v ) for k , v in self .meta .fine_grained_deps .items ()}
1625
1635
self .suppressed = list (self .meta .suppressed )
1626
1636
assert len (self .meta .dependencies ) == len (self .meta .dep_prios )
1627
1637
self .priorities = {id : pri
@@ -1630,6 +1640,7 @@ def __init__(self,
1630
1640
self .dep_line_map = {}
1631
1641
else :
1632
1642
# Parse the file (and then some) to get the dependencies.
1643
+ self .fine_grained_deps = {}
1633
1644
self .parse_file ()
1634
1645
self .suppressed = []
1635
1646
self .child_modules = set ()
@@ -1977,6 +1988,19 @@ def _patch_indirect_dependencies(self,
1977
1988
elif dep not in self .suppressed and dep in self .manager .missing_modules :
1978
1989
self .suppressed .append (dep )
1979
1990
1991
+ def find_fine_grained_deps (self ) -> None :
1992
+ assert self .tree is not None
1993
+ if '/typeshed/' in self .xpath or self .xpath .startswith ('typeshed/' ):
1994
+ # We don't track changes to typeshed -- the assumption is that they are only changed
1995
+ # as part of mypy updates, which will invalidate everything anyway.
1996
+ #
1997
+ # TODO: Not a reliable test, as we could have a package named typeshed.
1998
+ # TODO: Consider relaxing this -- maybe allow some typeshed changes to be tracked.
1999
+ return
2000
+ self .fine_grained_deps = get_dependencies (target = self .tree ,
2001
+ type_map = self .type_map (),
2002
+ python_version = self .options .python_version )
2003
+
1980
2004
def valid_references (self ) -> Set [str ]:
1981
2005
assert self .ancestors is not None
1982
2006
valid_refs = set (self .dependencies + self .suppressed + self .ancestors )
@@ -2003,7 +2027,9 @@ def write_cache(self) -> None:
2003
2027
dep_prios = self .dependency_priorities ()
2004
2028
new_interface_hash , self .meta = write_cache (
2005
2029
self .id , self .path , self .tree ,
2006
- list (self .dependencies ), list (self .suppressed ), list (self .child_modules ),
2030
+ list (self .dependencies ),
2031
+ {k : list (v ) for k , v in self .fine_grained_deps .items ()},
2032
+ list (self .suppressed ), list (self .child_modules ),
2007
2033
dep_prios , self .interface_hash , self .source_hash , self .ignore_all ,
2008
2034
self .manager )
2009
2035
if new_interface_hash == self .interface_hash :
@@ -2534,6 +2560,8 @@ def process_stale_scc(graph: Graph, scc: List[str], manager: BuildManager) -> No
2534
2560
graph [id ].transitive_error = True
2535
2561
for id in stale :
2536
2562
graph [id ].finish_passes ()
2563
+ if manager .options .cache_fine_grained :
2564
+ graph [id ].find_fine_grained_deps ()
2537
2565
graph [id ].generate_unused_ignore_notes ()
2538
2566
manager .flush_errors (manager .errors .file_messages (graph [id ].xpath ), False )
2539
2567
graph [id ].write_cache ()
0 commit comments