envconfig: Add type annotations

pull/5265/head
Dylan Baker 6 years ago
parent 25f8d28251
commit 205cf95f99
  1. 108
      mesonbuild/envconfig.py

@ -19,6 +19,8 @@ from . import mesonlib
from .mesonlib import EnvironmentException, MachineChoice, PerMachine
from . import mlog
_T = typing.TypeVar('_T')
# These classes contains all the data pulled from configuration files (native
# and cross file currently), and also assists with the reading environment
@ -69,7 +71,7 @@ CPU_FAMILES_64_BIT = [
class MesonConfigFile:
@classmethod
def from_config_parser(cls, parser: configparser.ConfigParser):
def from_config_parser(cls, parser: configparser.ConfigParser) -> typing.Dict[str, typing.Dict[str, typing.Dict[str, str]]]:
out = {}
# This is a bit hackish at the moment.
for s in parser.sections():
@ -106,55 +108,58 @@ class HasEnvVarFallback:
that we deal with environment variables will become more structured, and
this can be starting point.
"""
def __init__(self, fallback = True):
def __init__(self, fallback: bool = True):
self.fallback = fallback
class Properties(HasEnvVarFallback):
def __init__(
self,
properties: typing.Optional[typing.Dict[str, typing.Union[str, typing.List[str]]]] = None,
fallback = True):
fallback: bool = True):
super().__init__(fallback)
self.properties = properties or {}
self.properties = properties or {} # type: typing.Dict[str, typing.Union[str, typing.List[str]]]
def has_stdlib(self, language):
def has_stdlib(self, language: str) -> bool:
return language + '_stdlib' in self.properties
def get_stdlib(self, language):
# Some of get_stdlib, get_root, get_sys_root are wider than is actually
# true, but without heterogenious dict annotations it's not practical to
# narrow them
def get_stdlib(self, language: str) -> typing.Union[str, typing.List[str]]:
return self.properties[language + '_stdlib']
def get_root(self):
def get_root(self) -> typing.Optional[typing.Union[str, typing.List[str]]]:
return self.properties.get('root', None)
def get_sys_root(self):
def get_sys_root(self) -> typing.Optional[typing.Union[str, typing.List[str]]]:
return self.properties.get('sys_root', None)
def __eq__(self, other):
def __eq__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']:
if isinstance(other, type(self)):
return self.properties == other.properties
return NotImplemented
# TODO consider removing so Properties is less freeform
def __getitem__(self, key):
def __getitem__(self, key: str) -> typing.Any:
return self.properties[key]
# TODO consider removing so Properties is less freeform
def __contains__(self, item):
def __contains__(self, item: typing.Any) -> bool:
return item in self.properties
# TODO consider removing, for same reasons as above
def get(self, key, default=None):
def get(self, key: str, default: typing.Any = None) -> typing.Any:
return self.properties.get(key, default)
class MachineInfo:
def __init__(self, system, cpu_family, cpu, endian):
def __init__(self, system: str, cpu_family: str, cpu: str, endian: str):
self.system = system
self.cpu_family = cpu_family
self.cpu = cpu
self.endian = endian
self.is_64_bit = cpu_family in CPU_FAMILES_64_BIT
self.is_64_bit = cpu_family in CPU_FAMILES_64_BIT # type: bool
def __eq__(self, other):
def __eq__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']:
if self.__class__ is not other.__class__:
return NotImplemented
return \
@ -163,16 +168,16 @@ class MachineInfo:
self.cpu == other.cpu and \
self.endian == other.endian
def __ne__(self, other):
def __ne__(self, other: typing.Any) -> typing.Union[bool, 'NotImplemented']:
if self.__class__ is not other.__class__:
return NotImplemented
return not self.__eq__(other)
def __repr__(self):
def __repr__(self) -> str:
return '<MachineInfo: {} {} ({})>'.format(self.system, self.cpu_family, self.cpu)
@staticmethod
def from_literal(literal):
@classmethod
def from_literal(cls, literal: typing.Dict[str, str]) -> 'MachineInfo':
minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'}
if set(literal) < minimum_literal:
raise EnvironmentException(
@ -187,49 +192,45 @@ class MachineInfo:
if endian not in ('little', 'big'):
mlog.warning('Unknown endian %s' % endian)
return MachineInfo(
literal['system'],
cpu_family,
literal['cpu'],
endian)
return cls(literal['system'], cpu_family, literal['cpu'], endian)
def is_windows(self):
def is_windows(self) -> bool:
"""
Machine is windows?
"""
return self.system == 'windows'
def is_cygwin(self):
def is_cygwin(self) -> bool:
"""
Machine is cygwin?
"""
return self.system == 'cygwin'
def is_linux(self):
def is_linux(self) -> bool:
"""
Machine is linux?
"""
return self.system == 'linux'
def is_darwin(self):
def is_darwin(self) -> bool:
"""
Machine is Darwin (iOS/OS X)?
"""
return self.system in ('darwin', 'ios')
def is_android(self):
def is_android(self) -> bool:
"""
Machine is Android?
"""
return self.system == 'android'
def is_haiku(self):
def is_haiku(self) -> bool:
"""
Machine is Haiku?
"""
return self.system == 'haiku'
def is_openbsd(self):
def is_openbsd(self) -> bool:
"""
Machine is OpenBSD?
"""
@ -239,29 +240,28 @@ class MachineInfo:
# static libraries, and executables.
# Versioning is added to these names in the backends as-needed.
def get_exe_suffix(self):
def get_exe_suffix(self) -> str:
if self.is_windows() or self.is_cygwin():
return 'exe'
else:
return ''
def get_object_suffix(self):
def get_object_suffix(self) -> str:
if self.is_windows():
return 'obj'
else:
return 'o'
def libdir_layout_is_win(self):
return self.is_windows() \
or self.is_cygwin()
def libdir_layout_is_win(self) -> bool:
return self.is_windows() or self.is_cygwin()
class PerMachineDefaultable(PerMachine):
class PerMachineDefaultable(PerMachine[_T]):
"""Extends `PerMachine` with the ability to default from `None`s.
"""
def __init__(self):
def __init__(self) -> None:
super().__init__(None, None, None)
def default_missing(self):
def default_missing(self) -> None:
"""Default host to buid and target to host.
This allows just specifying nothing in the native case, just host in the
@ -273,7 +273,7 @@ class PerMachineDefaultable(PerMachine):
if self.target is None:
self.target = self.host
def miss_defaulting(self):
def miss_defaulting(self) -> None:
"""Unset definition duplicated from their previous to None
This is the inverse of ''default_missing''. By removing defaulted
@ -285,18 +285,17 @@ class PerMachineDefaultable(PerMachine):
if self.host == self.build:
self.host = None
class MachineInfos(PerMachineDefaultable):
def matches_build_machine(self, machine: MachineChoice):
class MachineInfos(PerMachineDefaultable[typing.Optional[MachineInfo]]):
def matches_build_machine(self, machine: MachineChoice) -> bool:
return self.build == self[machine]
class BinaryTable(HasEnvVarFallback):
def __init__(
self,
binaries: typing.Optional[typing.Dict[str, typing.Union[str, typing.List[str]]]] = None,
fallback = True):
fallback: bool = True):
super().__init__(fallback)
self.binaries = binaries or {}
self.binaries = binaries or {} # type: typing.Dict[str, typing.Union[str, typing.List[str]]]
for name, command in self.binaries.items():
if not isinstance(command, (list, str)):
# TODO generalize message
@ -325,10 +324,10 @@ class BinaryTable(HasEnvVarFallback):
'cmake': 'CMAKE',
'qmake': 'QMAKE',
'pkgconfig': 'PKG_CONFIG',
}
} # type: typing.Dict[str, str]
@staticmethod
def detect_ccache():
def detect_ccache() -> typing.List[str]:
try:
subprocess.check_call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError):
@ -336,14 +335,14 @@ class BinaryTable(HasEnvVarFallback):
return ['ccache']
@classmethod
def _warn_about_lang_pointing_to_cross(cls, compiler_exe, evar):
def _warn_about_lang_pointing_to_cross(cls, compiler_exe: str, evar: str) -> None:
evar_str = os.environ.get(evar, 'WHO_WOULD_CALL_THEIR_COMPILER_WITH_THIS_NAME')
if evar_str == compiler_exe:
mlog.warning('''Env var %s seems to point to the cross compiler.
This is probably wrong, it should always point to the native compiler.''' % evar)
@classmethod
def parse_entry(cls, entry):
def parse_entry(cls, entry: typing.Union[str, typing.List[str]]) -> typing.Tuple[typing.List[str], typing.List[str]]:
compiler = mesonlib.stringlistify(entry)
# Ensure ccache exists and remove it if it doesn't
if compiler[0] == 'ccache':
@ -354,8 +353,8 @@ This is probably wrong, it should always point to the native compiler.''' % evar
# Return value has to be a list of compiler 'choices'
return compiler, ccache
def lookup_entry(self, name):
"""Lookup binary
def lookup_entry(self, name: str) -> typing.Optional[typing.List[str]]:
"""Lookup binaryk
Returns command with args as list if found, Returns `None` if nothing is
found.
@ -404,11 +403,12 @@ class Directories:
self.sharedstatedir = sharedstatedir
self.sysconfdir = sysconfdir
def __contains__(self, key: str) -> str:
def __contains__(self, key: str) -> bool:
return hasattr(self, key)
def __getitem__(self, key: str) -> str:
return getattr(self, key)
def __getitem__(self, key: str) -> typing.Optional[str]:
# Mypy can't figure out what to do with getattr here, so we'll case for it
return typing.cast(typing.Optional[str], getattr(self, key))
def __setitem__(self, key: str, value: typing.Optional[str]) -> None:
setattr(self, key, value)

Loading…
Cancel
Save