allow some ObjectHolder subclasses to continue to be generic

ExternalProgram and CustomTarget have some use cases for producing
subclassed interpreter holders with more specific types and methods. In
order for those subclasses to properly refer to their held_object, we
need a shared base class that is still generic, though bound.

For the derived held objects, inherit from the base class and specify
the final types as the module-specific type.
pull/12106/head
Eli Schwartz 1 year ago
parent 13b626b67b
commit 277151450a
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 18
      mesonbuild/interpreter/interpreterobjects.py
  2. 6
      mesonbuild/modules/hotdoc.py
  3. 8
      mesonbuild/modules/python.py

@ -559,8 +559,10 @@ class DependencyHolder(ObjectHolder[Dependency]):
new_dep = self.held_object.generate_link_whole_dependency() new_dep = self.held_object.generate_link_whole_dependency()
return new_dep return new_dep
class ExternalProgramHolder(ObjectHolder[ExternalProgram]): _EXTPROG = T.TypeVar('_EXTPROG', bound=ExternalProgram)
def __init__(self, ep: ExternalProgram, interpreter: 'Interpreter') -> None:
class _ExternalProgramHolder(ObjectHolder[_EXTPROG]):
def __init__(self, ep: _EXTPROG, interpreter: 'Interpreter') -> None:
super().__init__(ep, interpreter) super().__init__(ep, interpreter)
self.methods.update({'found': self.found_method, self.methods.update({'found': self.found_method,
'path': self.path_method, 'path': self.path_method,
@ -606,6 +608,9 @@ class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
def found(self) -> bool: def found(self) -> bool:
return self.held_object.found() return self.held_object.found()
class ExternalProgramHolder(_ExternalProgramHolder[ExternalProgram]):
pass
class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]): class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'): def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'):
super().__init__(el, interpreter) super().__init__(el, interpreter)
@ -969,8 +974,10 @@ class CustomTargetIndexHolder(ObjectHolder[build.CustomTargetIndex]):
assert self.interpreter.backend is not None assert self.interpreter.backend is not None
return self.interpreter.backend.get_target_filename_abs(self.held_object) return self.interpreter.backend.get_target_filename_abs(self.held_object)
class CustomTargetHolder(ObjectHolder[build.CustomTarget]): _CT = T.TypeVar('_CT', bound=build.CustomTarget)
def __init__(self, target: 'build.CustomTarget', interp: 'Interpreter'):
class _CustomTargetHolder(ObjectHolder[_CT]):
def __init__(self, target: _CT, interp: 'Interpreter'):
super().__init__(target, interp) super().__init__(target, interp)
self.methods.update({'full_path': self.full_path_method, self.methods.update({'full_path': self.full_path_method,
'to_list': self.to_list_method, 'to_list': self.to_list_method,
@ -1007,6 +1014,9 @@ class CustomTargetHolder(ObjectHolder[build.CustomTarget]):
except IndexError: except IndexError:
raise InvalidArguments(f'Index {other} out of bounds of custom target {self.held_object.name} output of size {len(self.held_object)}.') raise InvalidArguments(f'Index {other} out of bounds of custom target {self.held_object.name} output of size {len(self.held_object)}.')
class CustomTargetHolder(_CustomTargetHolder[build.CustomTarget]):
pass
class RunTargetHolder(ObjectHolder[build.RunTarget]): class RunTargetHolder(ObjectHolder[build.RunTarget]):
pass pass

@ -28,7 +28,7 @@ from ..interpreterbase import (
InvalidArguments, noPosargs, noKwargs, typed_kwargs, FeatureDeprecated, InvalidArguments, noPosargs, noKwargs, typed_kwargs, FeatureDeprecated,
ContainerTypeInfo, KwargInfo, typed_pos_args ContainerTypeInfo, KwargInfo, typed_pos_args
) )
from ..interpreter import CustomTargetHolder from ..interpreter.interpreterobjects import _CustomTargetHolder
from ..interpreter.type_checking import NoneType from ..interpreter.type_checking import NoneType
from ..programs import ExternalProgram from ..programs import ExternalProgram
@ -364,8 +364,8 @@ class HotdocTargetBuilder:
return (target, install_script) return (target, install_script)
class HotdocTargetHolder(CustomTargetHolder): class HotdocTargetHolder(_CustomTargetHolder['HotdocTarget']):
def __init__(self, target, interp): def __init__(self, target: HotdocTarget, interp):
super().__init__(target, interp) super().__init__(target, interp)
self.methods.update({'config_path': self.config_path_method}) self.methods.update({'config_path': self.config_path_method})

@ -24,8 +24,8 @@ from ..build import known_shmod_kwargs, CustomTarget, CustomTargetIndex, BuildTa
from ..dependencies import NotFoundDependency from ..dependencies import NotFoundDependency
from ..dependencies.detect import get_dep_identifier, find_external_dependency from ..dependencies.detect import get_dep_identifier, find_external_dependency
from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase
from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs from ..interpreter import extract_required_kwarg, permitted_dependency_kwargs, primitives as P_OBJ
from ..interpreter import primitives as P_OBJ from ..interpreter.interpreterobjects import _ExternalProgramHolder
from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW, SHARED_MOD_KWS from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW, SHARED_MOD_KWS
from ..interpreterbase import ( from ..interpreterbase import (
noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo,
@ -114,9 +114,9 @@ _PURE_KW = KwargInfo('pure', (bool, NoneType))
_SUBDIR_KW = KwargInfo('subdir', str, default='') _SUBDIR_KW = KwargInfo('subdir', str, default='')
_DEFAULTABLE_SUBDIR_KW = KwargInfo('subdir', (str, NoneType)) _DEFAULTABLE_SUBDIR_KW = KwargInfo('subdir', (str, NoneType))
class PythonInstallation(ExternalProgramHolder): class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']):
def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'):
ExternalProgramHolder.__init__(self, python, interpreter) _ExternalProgramHolder.__init__(self, python, interpreter)
info = python.info info = python.info
prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix')) prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
assert isinstance(prefix, str), 'for mypy' assert isinstance(prefix, str), 'for mypy'

Loading…
Cancel
Save