Skip to content

Commit

Permalink
environment: make fully type safe
Browse files Browse the repository at this point in the history
This as much as anything is to stop lying to envconfig about the
potential types it will be given.
  • Loading branch information
dcbaker committed Feb 28, 2025
1 parent f4099e7 commit d0f38a0
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 8 deletions.
2 changes: 2 additions & 0 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,8 @@ def get_global_options(lang: str,

comp_options = env.options.get(comp_key, [])
link_options = env.options.get(largkey, [])
assert isinstance(comp_options, (str, list)), 'for mypy'
assert isinstance(link_options, (str, list)), 'for mypy'

cargs = options.UserStringArrayOption(
argkey.name,
Expand Down
15 changes: 12 additions & 3 deletions mesonbuild/envconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
from . import mlog
from pathlib import Path

if T.TYPE_CHECKING:
from .options import ElementaryOptionValues


# These classes contains all the data pulled from configuration files (native
# and cross file currently), and also assists with the reading environment
Expand Down Expand Up @@ -153,7 +156,7 @@ class CMakeSkipCompilerTest(Enum):
class Properties:
def __init__(
self,
properties: T.Optional[T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]] = None,
properties: T.Optional[T.Dict[str, ElementaryOptionValues]] = None,
):
self.properties = properties or {}

Expand Down Expand Up @@ -270,7 +273,13 @@ def __repr__(self) -> str:
return f'<MachineInfo: {self.system} {self.cpu_family} ({self.cpu})>'

@classmethod
def from_literal(cls, literal: T.Dict[str, str]) -> 'MachineInfo':
def from_literal(cls, raw: T.Dict[str, ElementaryOptionValues]) -> 'MachineInfo':
# We don't have enough type information to be sure of what we loaded
# So we need to accept that this might have ElementaryOptionValues, but
# then ensure that it's actually strings, since that's what the
# [*_machine] section should have.
assert all(isinstance(v, str) for v in raw.values()), 'for mypy'
literal = T.cast('T.Dict[str, str]', raw)
minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'}
if set(literal) < minimum_literal:
raise EnvironmentException(
Expand Down Expand Up @@ -389,7 +398,7 @@ class BinaryTable:

def __init__(
self,
binaries: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
binaries: T.Optional[T.Mapping[str, ElementaryOptionValues]] = None,
):
self.binaries: T.Dict[str, T.List[str]] = {}
if binaries:
Expand Down
10 changes: 5 additions & 5 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@
from mesonbuild import envconfig

if T.TYPE_CHECKING:
from configparser import ConfigParser

from .compilers import Compiler
from .compilers.mixins.visualstudio import VisualStudioLikeCompiler
from .options import ElementaryOptionValues
from .wrap.wrap import Resolver
from . import cargo

Expand Down Expand Up @@ -633,7 +632,7 @@ def __init__(self, source_dir: str, build_dir: str, cmd_options: coredata.Shared
#
# Note that order matters because of 'buildtype', if it is after
# 'optimization' and 'debug' keys, it override them.
self.options: T.MutableMapping[OptionKey, T.Union[str, T.List[str]]] = collections.OrderedDict()
self.options: T.MutableMapping[OptionKey, ElementaryOptionValues] = collections.OrderedDict()

self.machinestore = machinefile.MachineFileStore(self.coredata.config_files, self.coredata.cross_files, self.source_dir)

Expand Down Expand Up @@ -701,7 +700,7 @@ def __init__(self, source_dir: str, build_dir: str, cmd_options: coredata.Shared
# Store a global state of Cargo dependencies
self.cargo: T.Optional[cargo.Interpreter] = None

def mfilestr2key(self, machine_file_string: str, section_subproject: str, machine: MachineChoice):
def mfilestr2key(self, machine_file_string: str, section_subproject: str, machine: MachineChoice) -> OptionKey:
key = OptionKey.from_string(machine_file_string)
assert key.machine == MachineChoice.HOST
if key.subproject:
Expand All @@ -712,7 +711,8 @@ def mfilestr2key(self, machine_file_string: str, section_subproject: str, machin
return key.evolve(machine=machine)
return key

def _load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
def _load_machine_file_options(self, config: T.Mapping[str, T.Mapping[str, ElementaryOptionValues]],
properties: Properties, machine: MachineChoice) -> None:
"""Read the contents of a Machine file and put it in the options store."""

# Look for any options in the deprecated paths section, warn about
Expand Down
1 change: 1 addition & 0 deletions run_mypy.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
# 'mesonbuild/coredata.py',
'mesonbuild/depfile.py',
'mesonbuild/envconfig.py',
'mesonbuild/environment.py',
'mesonbuild/interpreter/compiler.py',
'mesonbuild/interpreter/mesonmain.py',
'mesonbuild/interpreter/interpreterobjects.py',
Expand Down

0 comments on commit d0f38a0

Please sign in to comment.