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
pull/11516/head
Dylan Baker 2 years ago committed by Eli Schwartz
parent 62c269d088
commit 7c2ac4f8fe
  1. 4
      mesonbuild/coredata.py
  2. 4
      mesonbuild/minstall.py
  3. 31
      mesonbuild/utils/universal.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:

@ -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.'''

@ -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

Loading…
Cancel
Save