aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2023-03-09 10:20:57 -0800
committerEli Schwartz <eschwartz93@gmail.com>2023-03-09 19:03:44 -0500
commit7c2ac4f8fe2bda306adc73572d8f8e43010456cb (patch)
tree97c23889e0aec53ff81e12ddc19acfae00e26267
parent62c269d08859747ba558e90bc98505e6325ef678 (diff)
downloadmeson-7c2ac4f8fe2bda306adc73572d8f8e43010456cb.zip
meson-7c2ac4f8fe2bda306adc73572d8f8e43010456cb.tar.gz
meson-7c2ac4f8fe2bda306adc73572d8f8e43010456cb.tar.bz2
utils: fix annotation of pickle_load
It's actually Generic, and we should use Generic annotations to get the correct result. This means that we don't have to assert or cast the return type, because mypy just knowns
-rw-r--r--mesonbuild/coredata.py4
-rw-r--r--mesonbuild/minstall.py4
-rw-r--r--mesonbuild/utils/universal.py31
3 files changed, 28 insertions, 11 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 62c81ff..38d6fcf 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -1056,9 +1056,7 @@ def major_versions_differ(v1: str, v2: str) -> bool:
def load(build_dir: str) -> CoreData:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
- obj = pickle_load(filename, 'Coredata', CoreData)
- assert isinstance(obj, CoreData), 'for mypy'
- return obj
+ return pickle_load(filename, 'Coredata', CoreData)
def save(obj: CoreData, build_dir: str) -> str:
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 969e09e..6922c38 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -131,9 +131,7 @@ class DirMaker:
def load_install_data(fname: str) -> InstallData:
- obj = pickle_load(fname, 'InstallData', InstallData)
- assert isinstance(obj, InstallData), 'fo mypy'
- return obj
+ return pickle_load(fname, 'InstallData', InstallData)
def is_executable(path: str, follow_symlinks: bool = False) -> bool:
'''Checks whether any of the "x" bits are set in the source file mode.'''
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