Cache the result of python.find_installation()

This avoids running sanity checks everytime find_installation() is
called.
pull/10047/head
Xavier Claessens 3 years ago committed by Xavier Claessens
parent 7a926d8dff
commit c5c02b72e1
  1. 63
      mesonbuild/modules/python.py

@ -637,6 +637,7 @@ class PythonModule(ExtensionModule):
@FeatureNew('Python Module', '0.46.0')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self.installations: T.Dict[str, ExternalProgram] = {}
self.methods.update({
'find_installation': self.find_installation,
})
@ -658,6 +659,31 @@ class PythonModule(ExtensionModule):
else:
return None
def _find_installation_impl(self, state: 'ModuleState', display_name: str, name_or_path: str) -> ExternalProgram:
if not name_or_path:
python = PythonExternalProgram('python3', mesonlib.python_command)
else:
tmp_python = ExternalProgram.from_entry(display_name, name_or_path)
python = PythonExternalProgram(display_name, ext_prog=tmp_python)
if not python.found() and mesonlib.is_windows():
pythonpath = self._get_win_pythonpath(name_or_path)
if pythonpath is not None:
name_or_path = pythonpath
python = PythonExternalProgram(name_or_path)
# Last ditch effort, python2 or python3 can be named python
# on various platforms, let's not give up just yet, if an executable
# named python is available and has a compatible version, let's use
# it
if not python.found() and name_or_path in ['python2', 'python3']:
python = PythonExternalProgram('python')
if python.found() and not python.sanity(state):
python = NonExistingExternalProgram()
return python
@disablerIfNotFound
@typed_pos_args('python.find_installation', optargs=[str])
@typed_kwargs(
@ -670,9 +696,6 @@ class PythonModule(ExtensionModule):
kwargs: 'FindInstallationKw') -> ExternalProgram:
feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0')
disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check)
want_modules = kwargs['modules']
found_modules: T.List[str] = []
missing_modules: T.List[str] = []
# FIXME: this code is *full* of sharp corners. It assumes that it's
# going to get a string value (or now a list of length 1), of `python2`
@ -691,25 +714,14 @@ class PythonModule(ExtensionModule):
mlog.log('Program', name_or_path or 'python', 'found:', mlog.red('NO'), '(disabled by:', mlog.bold(feature), ')')
return NonExistingExternalProgram()
if not name_or_path:
python = PythonExternalProgram('python3', mesonlib.python_command)
else:
tmp_python = ExternalProgram.from_entry(display_name, name_or_path)
python = PythonExternalProgram(display_name, ext_prog=tmp_python)
if not python.found() and mesonlib.is_windows():
pythonpath = self._get_win_pythonpath(name_or_path)
if pythonpath is not None:
name_or_path = pythonpath
python = PythonExternalProgram(name_or_path)
# Last ditch effort, python2 or python3 can be named python
# on various platforms, let's not give up just yet, if an executable
# named python is available and has a compatible version, let's use
# it
if not python.found() and name_or_path in ['python2', 'python3']:
python = PythonExternalProgram('python')
python = self.installations.get(name_or_path)
if not python:
python = self._find_installation_impl(state, display_name, name_or_path)
self.installations[name_or_path] = python
want_modules = kwargs['modules']
found_modules: T.List[str] = []
missing_modules: T.List[str] = []
if python.found() and want_modules:
for mod in want_modules:
p, *_ = mesonlib.Popen_safe(
@ -743,14 +755,7 @@ class PythonModule(ExtensionModule):
raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules)))
return NonExistingExternalProgram()
else:
sane = python.sanity(state)
if sane:
return python
else:
if required:
raise mesonlib.MesonException(f'{python} is not a valid python or it is missing distutils')
return NonExistingExternalProgram()
return python
raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).')

Loading…
Cancel
Save