aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/utils/universal.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/utils/universal.py')
-rw-r--r--mesonbuild/utils/universal.py31
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