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: def load(build_dir: str) -> CoreData:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
obj = pickle_load(filename, 'Coredata', CoreData) return pickle_load(filename, 'Coredata', CoreData)
assert isinstance(obj, CoreData), 'for mypy'
return obj
def save(obj: CoreData, build_dir: str) -> str: def save(obj: CoreData, build_dir: str) -> str:

@ -131,9 +131,7 @@ class DirMaker:
def load_install_data(fname: str) -> InstallData: def load_install_data(fname: str) -> InstallData:
obj = pickle_load(fname, 'InstallData', InstallData) return pickle_load(fname, 'InstallData', InstallData)
assert isinstance(obj, InstallData), 'fo mypy'
return obj
def is_executable(path: str, follow_symlinks: bool = False) -> bool: def is_executable(path: str, follow_symlinks: bool = False) -> bool:
'''Checks whether any of the "x" bits are set in the source file mode.''' '''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 from .core import MesonException, HoldableObject
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from typing_extensions import Literal from typing_extensions import Literal, Protocol
from .._typing import ImmutableListProtocol from .._typing import ImmutableListProtocol
from ..build import ConfigurationData from ..build import ConfigurationData
from ..coredata import KeyedOptionDictType, UserOption from ..coredata import KeyedOptionDictType, UserOption
from ..environment import Environment
from ..compilers.compilers import Compiler 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] FileOrString = T.Union['File', str]
_T = T.TypeVar('_T') _T = T.TypeVar('_T')
@ -2326,7 +2339,8 @@ class OptionKey:
"""Convenience method to check if this is a base option.""" """Convenience method to check if this is a base option."""
return self.type is OptionType.BASE 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.' load_fail_msg = f'{object_name} file {filename!r} is corrupted. Try with a fresh build tree.'
try: try:
with open(filename, 'rb') as f: 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') f'meson setup {build_dir} --wipe')
if not isinstance(obj, object_type): if not isinstance(obj, object_type):
raise MesonException(load_fail_msg) 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 version as coredata_version
from ..coredata import major_versions_differ, MesonVersionMismatchException 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): if major_versions_differ(version, coredata_version):
raise MesonVersionMismatchException(version, coredata_version) raise MesonVersionMismatchException(version, coredata_version)
return obj return obj

Loading…
Cancel
Save