@@ -137,7 +137,12 @@ def get_all_stub_files(
137137 module_name = entry .name [: - len (".pyi" )]
138138 else :
139139 continue
140- if search_context .version < versions [module_name ]:
140+ version = versions [module_name ]
141+ if search_context .version < version .min :
142+ continue
143+ if version .max is not None and search_context .version > version .max :
144+ continue
145+ if typeshed_dir .name != "@python2" and version .in_python2 :
141146 continue
142147 if entry .is_dir ():
143148 seen = yield from _get_all_stub_files_from_directory (
@@ -223,35 +228,60 @@ def get_stub_file_name(
223228
224229 # 5. typeshed
225230 versions = get_typeshed_versions (search_context .typeshed )
226- if (
227- top_level_name not in versions
228- or search_context .version < versions [top_level_name ]
229- ):
231+ if top_level_name not in versions :
232+ return None
233+ version = versions [top_level_name ]
234+ if search_context .version < version .min :
235+ return None
236+ if version .max is not None and search_context .version > version .max :
230237 return None
231238
232239 if search_context .version [0 ] == 2 :
233240 python2_dir = search_context .typeshed / "@python2"
234241 stub = _find_stub_in_dir (python2_dir , module_name )
235- if stub is not None :
242+ if stub is not None or version . in_python2 :
236243 return stub
237244
238245 return _find_stub_in_dir (search_context .typeshed , module_name )
239246
240247
248+ class _VersionData (NamedTuple ):
249+ min : PythonVersion
250+ max : Optional [PythonVersion ]
251+ # whether it is present in @python2
252+ in_python2 : bool
253+
254+
241255@lru_cache ()
242- def get_typeshed_versions (typeshed : Path ) -> Dict [str , PythonVersion ]:
256+ def get_typeshed_versions (typeshed : Path ) -> Dict [str , _VersionData ]:
243257 versions = {}
258+ python2_files = set (os .listdir (typeshed / "@python2" ))
244259 with (typeshed / "VERSIONS" ).open () as f :
245260 for line in f :
246261 line = line .strip ()
247262 if not line or line .startswith ("#" ):
248263 continue
249264 module , version = line .split (": " )
250- major , minor = version .split ("." )
251- versions [module ] = (int (major ), int (minor ))
265+ if "-" in version :
266+ min_version_str , max_version_str = version .split ("-" )
267+ else :
268+ min_version_str = version
269+ max_version_str = None
270+ if max_version_str :
271+ max_version = _parse_version (max_version_str )
272+ else :
273+ max_version = None
274+ min_version = _parse_version (min_version_str )
275+ python2_only = module in python2_files or module + ".pyi" in python2_files
276+ versions [module ] = _VersionData (min_version , max_version , python2_only )
252277 return versions
253278
254279
280+ def _parse_version (version : str ) -> PythonVersion :
281+ major , minor = version .split ("." )
282+ return (int (major ), int (minor ))
283+
284+
255285def _find_stub_in_dir (stubdir : Path , module : ModulePath ) -> Optional [Path ]:
256286 if not module :
257287 init_name = stubdir / "__init__.pyi"
0 commit comments