diff options
author | Eli Schwartz <eschwartz@archlinux.org> | 2023-02-13 19:50:03 -0500 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2023-02-22 10:32:09 -0800 |
commit | 9fa4da3ba94cd1bd41917c93742396bd3f94330f (patch) | |
tree | 2da865455ef0f451b8955c1b7a7aa88763eec1cd /mesonbuild/dependencies/python.py | |
parent | 6719724c7c6ddecba60cc27f60a07862bb707615 (diff) | |
download | meson-9fa4da3ba94cd1bd41917c93742396bd3f94330f.zip meson-9fa4da3ba94cd1bd41917c93742396bd3f94330f.tar.gz meson-9fa4da3ba94cd1bd41917c93742396bd3f94330f.tar.bz2 |
python module/dependency: move the specialized external program
In preparation for handling more work inside dependencies.*, we need to
be able to run a PythonExternalProgram from the python dependency. Move
most of the definition -- but only the parts that have no interest in a
ModuleState -- and subclass a bit of sanity checking that we need to
handle specially when used in the module.
Diffstat (limited to 'mesonbuild/dependencies/python.py')
-rw-r--r-- | mesonbuild/dependencies/python.py | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 06dd700..f3a8444 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -13,18 +13,95 @@ # limitations under the License. from __future__ import annotations +import json, sysconfig from pathlib import Path -import sysconfig import typing as T -from .. import mlog +from .. import mesonlib, mlog from .base import DependencyMethods, SystemDependency from .factory import DependencyFactory from ..environment import detect_cpu_family +from ..programs import ExternalProgram if T.TYPE_CHECKING: + from typing_extensions import TypedDict + from ..environment import Environment + class PythonIntrospectionDict(TypedDict): + + install_paths: T.Dict[str, str] + is_pypy: bool + is_venv: bool + link_libpython: bool + sysconfig_paths: T.Dict[str, str] + paths: T.Dict[str, str] + platform: str + suffix: str + variables: T.Dict[str, str] + version: str + + +class BasicPythonExternalProgram(ExternalProgram): + def __init__(self, name: str, command: T.Optional[T.List[str]] = None, + ext_prog: T.Optional[ExternalProgram] = None): + if ext_prog is None: + super().__init__(name, command=command, silent=True) + else: + self.name = name + self.command = ext_prog.command + self.path = ext_prog.path + + # We want strong key values, so we always populate this with bogus data. + # Otherwise to make the type checkers happy we'd have to do .get() for + # everycall, even though we know that the introspection data will be + # complete + self.info: 'PythonIntrospectionDict' = { + 'install_paths': {}, + 'is_pypy': False, + 'is_venv': False, + 'link_libpython': False, + 'sysconfig_paths': {}, + 'paths': {}, + 'platform': 'sentinal', + 'suffix': 'sentinel', + 'variables': {}, + 'version': '0.0', + } + self.pure: bool = True + + def _check_version(self, version: str) -> bool: + if self.name == 'python2': + return mesonlib.version_compare(version, '< 3.0') + elif self.name == 'python3': + return mesonlib.version_compare(version, '>= 3.0') + return True + + def sanity(self) -> bool: + # Sanity check, we expect to have something that at least quacks in tune + + import importlib.resources + + with importlib.resources.path('mesonbuild.scripts', 'python_info.py') as f: + cmd = self.get_command() + [str(f)] + p, stdout, stderr = mesonlib.Popen_safe(cmd) + + try: + info = json.loads(stdout) + except json.JSONDecodeError: + info = None + mlog.debug('Could not introspect Python (%s): exit code %d' % (str(p.args), p.returncode)) + mlog.debug('Program stdout:\n') + mlog.debug(stdout) + mlog.debug('Program stderr:\n') + mlog.debug(stderr) + + if info is not None and self._check_version(info['version']): + self.info = T.cast('PythonIntrospectionDict', info) + return True + else: + return False + class Python3DependencySystem(SystemDependency): def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: |