1818 from argparse import ArgumentParser
1919 from collections .abc import Callable , Generator , Iterable , Mapping , Sequence
2020
21- from virtualenv .app_data . base import AppData
21+ from .app_data import AppData
2222LOGGER = logging .getLogger (__name__ )
2323
2424
@@ -27,8 +27,8 @@ class Builtin(Discover):
2727 app_data : AppData
2828 try_first_with : Sequence [str ]
2929
30- def __init__ (self , options ) -> None :
31- super ().__init__ (options )
30+ def __init__ (self , options , cache = None ) -> None :
31+ super ().__init__ (options , cache )
3232 self .python_spec = options .python or [sys .executable ]
3333 if self ._env .get ("VIRTUALENV_PYTHON" ):
3434 self .python_spec = self .python_spec [1 :] + self .python_spec [:1 ] # Rotate the list
@@ -60,7 +60,7 @@ def add_parser_arguments(cls, parser: ArgumentParser) -> None:
6060
6161 def run (self ) -> PythonInfo | None :
6262 for python_spec in self .python_spec :
63- result = get_interpreter (python_spec , self .try_first_with , self .app_data , self ._env )
63+ result = get_interpreter (python_spec , self .try_first_with , self .app_data , self .cache , self . _env )
6464 if result is not None :
6565 return result
6666 return None
@@ -71,13 +71,17 @@ def __repr__(self) -> str:
7171
7272
7373def get_interpreter (
74- key , try_first_with : Iterable [str ], app_data : AppData | None = None , env : Mapping [str , str ] | None = None
74+ key ,
75+ try_first_with : Iterable [str ],
76+ app_data : AppData | None = None ,
77+ cache = None ,
78+ env : Mapping [str , str ] | None = None ,
7579) -> PythonInfo | None :
7680 spec = PythonSpec .from_string_spec (key )
7781 LOGGER .info ("find interpreter for spec %r" , spec )
7882 proposed_paths = set ()
7983 env = os .environ if env is None else env
80- for interpreter , impl_must_match in propose_interpreters (spec , try_first_with , app_data , env ):
84+ for interpreter , impl_must_match in propose_interpreters (spec , try_first_with , app_data , cache , env ):
8185 key = interpreter .system_executable , impl_must_match
8286 if key in proposed_paths :
8387 continue
@@ -93,6 +97,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
9397 spec : PythonSpec ,
9498 try_first_with : Iterable [str ],
9599 app_data : AppData | None = None ,
100+ cache = None ,
96101 env : Mapping [str , str ] | None = None ,
97102) -> Generator [tuple [PythonInfo , bool ], None , None ]:
98103 # 0. if it's a path and exists, and is absolute path, this is the only option we consider
@@ -108,7 +113,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
108113 exe_id = fs_path_id (exe_raw )
109114 if exe_id not in tested_exes :
110115 tested_exes .add (exe_id )
111- yield PythonInfo .from_exe (exe_raw , app_data , env = env ), True
116+ yield PythonInfo .from_exe (exe_raw , app_data , cache , env = env ), True
112117 return
113118
114119 # 1. try with first
@@ -124,7 +129,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
124129 if exe_id in tested_exes :
125130 continue
126131 tested_exes .add (exe_id )
127- yield PythonInfo .from_exe (exe_raw , app_data , env = env ), True
132+ yield PythonInfo .from_exe (exe_raw , app_data , cache , env = env ), True
128133
129134 # 1. if it's a path and exists
130135 if spec .path is not None :
@@ -137,12 +142,12 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
137142 exe_id = fs_path_id (exe_raw )
138143 if exe_id not in tested_exes :
139144 tested_exes .add (exe_id )
140- yield PythonInfo .from_exe (exe_raw , app_data , env = env ), True
145+ yield PythonInfo .from_exe (exe_raw , app_data , cache , env = env ), True
141146 if spec .is_abs :
142147 return
143148 else :
144149 # 2. otherwise try with the current
145- current_python = PythonInfo .current_system (app_data )
150+ current_python = PythonInfo .current_system (app_data , cache )
146151 exe_raw = str (current_python .executable )
147152 exe_id = fs_path_id (exe_raw )
148153 if exe_id not in tested_exes :
@@ -153,7 +158,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
153158 if IS_WIN :
154159 from .windows import propose_interpreters # noqa: PLC0415
155160
156- for interpreter in propose_interpreters (spec , app_data , env ):
161+ for interpreter in propose_interpreters (spec , app_data , cache , env ):
157162 exe_raw = str (interpreter .executable )
158163 exe_id = fs_path_id (exe_raw )
159164 if exe_id in tested_exes :
@@ -171,7 +176,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
171176 if exe_id in tested_exes :
172177 continue
173178 tested_exes .add (exe_id )
174- interpreter = PathPythonInfo .from_exe (exe_raw , app_data , raise_on_error = False , env = env )
179+ interpreter = PathPythonInfo .from_exe (exe_raw , app_data , cache , raise_on_error = False , env = env )
175180 if interpreter is not None :
176181 yield interpreter , impl_must_match
177182
@@ -184,7 +189,7 @@ def propose_interpreters( # noqa: C901, PLR0912, PLR0915
184189 uv_python_path = user_data_path ("uv" ) / "python"
185190
186191 for exe_path in uv_python_path .glob ("*/bin/python" ):
187- interpreter = PathPythonInfo .from_exe (str (exe_path ), app_data , raise_on_error = False , env = env )
192+ interpreter = PathPythonInfo .from_exe (str (exe_path ), app_data , cache , raise_on_error = False , env = env )
188193 if interpreter is not None :
189194 yield interpreter , True
190195
0 commit comments