diff options
Diffstat (limited to 'mesonbuild/utils/universal.py')
-rw-r--r-- | mesonbuild/utils/universal.py | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index b0cc252..bd136ba 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -37,13 +37,26 @@ from mesonbuild import mlog from .core import MesonException, HoldableObject if T.TYPE_CHECKING: - from typing_extensions import Literal + from typing_extensions import Literal, Protocol from .._typing import ImmutableListProtocol from ..build import ConfigurationData from ..coredata import KeyedOptionDictType, UserOption + from ..environment import Environment from ..compilers.compilers import Compiler + class _EnvPickleLoadable(Protocol): + + environment: Environment + + class _VerPickleLoadable(Protocol): + + version: str + + # A generic type for pickle_load. This allows any type that has either a + # .version or a .environment to be passed. + _PL = T.TypeVar('_PL', bound=T.Union[_EnvPickleLoadable, _VerPickleLoadable]) + FileOrString = T.Union['File', str] _T = T.TypeVar('_T') @@ -2326,7 +2339,8 @@ class OptionKey: """Convenience method to check if this is a base option.""" return self.type is OptionType.BASE -def pickle_load(filename: str, object_name: str, object_type: T.Type) -> T.Any: + +def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL]) -> _PL: load_fail_msg = f'{object_name} file {filename!r} is corrupted. Try with a fresh build tree.' try: with open(filename, 'rb') as f: @@ -2342,11 +2356,18 @@ def pickle_load(filename: str, object_name: str, object_type: T.Type) -> T.Any: f'meson setup {build_dir} --wipe') if not isinstance(obj, object_type): raise MesonException(load_fail_msg) + + # Because these Protocols are not available at runtime (and cannot be made + # available at runtime until we drop support for Python < 3.8), we have to + # do a bit of hackery so that mypy understands what's going on here + version: str + if hasattr(obj, 'version'): + version = T.cast('_VerPickleLoadable', obj).version + else: + version = T.cast('_EnvPickleLoadable', obj).environment.coredata.version + from ..coredata import version as coredata_version from ..coredata import major_versions_differ, MesonVersionMismatchException - version = getattr(obj, 'version', None) - if version is None: - version = obj.environment.coredata.version if major_versions_differ(version, coredata_version): raise MesonVersionMismatchException(version, coredata_version) return obj |