aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorEli Schwartz <eschwartz@archlinux.org>2022-02-10 21:39:50 -0500
committerEli Schwartz <eschwartz@archlinux.org>2022-02-14 20:40:41 -0500
commitc0b8e02d9fb1b58551b18e68ae188263dd90eb4c (patch)
treeac67d9907a21c04308b33f9a6889b88dad735de7 /mesonbuild
parentbab651a7a03b48ff909a49eabe2dbcef0e821496 (diff)
downloadmeson-c0b8e02d9fb1b58551b18e68ae188263dd90eb4c.zip
meson-c0b8e02d9fb1b58551b18e68ae188263dd90eb4c.tar.gz
meson-c0b8e02d9fb1b58551b18e68ae188263dd90eb4c.tar.bz2
FeatureNew: add mypy type annotations for subproject arg
Use a derived type when passing `subproject` around, so that mypy knows it's actually a SubProject, not a str. This means that passing anything other than a handle to the interpreter state's subproject attribute becomes a type violation, specifically when the order of the *four* different str arguments is typoed.
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/build.py5
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py3
-rw-r--r--mesonbuild/interpreter/primitives/range.py5
-rw-r--r--mesonbuild/interpreterbase/__init__.py4
-rw-r--r--mesonbuild/interpreterbase/baseobjects.py6
-rw-r--r--mesonbuild/interpreterbase/decorators.py7
-rw-r--r--mesonbuild/interpreterbase/interpreterbase.py4
-rw-r--r--mesonbuild/optinterpreter.py3
-rw-r--r--mesonbuild/wrap/wrap.py3
9 files changed, 28 insertions, 12 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 782f59c..27e6d36 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -49,6 +49,7 @@ if T.TYPE_CHECKING:
from ._typing import ImmutableListProtocol, ImmutableSetProtocol
from .backend.backends import Backend, ExecutableSerialisation
from .interpreter.interpreter import Test, SourceOutputs, Interpreter
+ from .interpreterbase import SubProject
from .mesonlib import FileMode, FileOrString
from .modules import ModuleState
from .mparser import BaseNode
@@ -514,7 +515,7 @@ class Target(HoldableObject):
name: str
subdir: str
- subproject: str
+ subproject: 'SubProject'
build_by_default: bool
for_machine: MachineChoice
@@ -675,7 +676,7 @@ class BuildTarget(Target):
install_dir: T.List[T.Union[str, bool]]
- def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice,
+ def __init__(self, name: str, subdir: str, subproject: 'SubProject', for_machine: MachineChoice,
sources: T.List['SourceOutputs'], objects, environment: environment.Environment, kwargs):
super().__init__(name, subdir, subproject, True, for_machine)
unity_opt = environment.coredata.get_option(OptionKey('unity'))
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index 6b7cbcd..989877e 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -31,6 +31,7 @@ if T.TYPE_CHECKING:
from . import kwargs
from .interpreter import Interpreter
from ..envconfig import MachineInfo
+ from ..interpreterbase import SubProject
from typing_extensions import TypedDict
@@ -40,7 +41,7 @@ if T.TYPE_CHECKING:
def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired',
- subproject: str,
+ subproject: 'SubProject',
feature_check: T.Optional[FeatureCheckBase] = None,
default: bool = True) -> T.Tuple[bool, bool, T.Optional[str]]:
val = kwargs.get('required', default)
diff --git a/mesonbuild/interpreter/primitives/range.py b/mesonbuild/interpreter/primitives/range.py
index 9054278..a35470c 100644
--- a/mesonbuild/interpreter/primitives/range.py
+++ b/mesonbuild/interpreter/primitives/range.py
@@ -10,8 +10,11 @@ from ...interpreterbase import (
InvalidArguments,
)
+if T.TYPE_CHECKING:
+ from ...interpreterbase import SubProject
+
class RangeHolder(MesonInterpreterObject, IterableObject):
- def __init__(self, start: int, stop: int, step: int, *, subproject: str) -> None:
+ def __init__(self, start: int, stop: int, step: int, *, subproject: 'SubProject') -> None:
super().__init__(subproject=subproject)
self.range = range(start, stop, step)
self.operators.update({
diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py
index 7c4b1db..13f55e5 100644
--- a/mesonbuild/interpreterbase/__init__.py
+++ b/mesonbuild/interpreterbase/__init__.py
@@ -57,6 +57,8 @@ __all__ = [
'InterpreterBase',
+ 'SubProject',
+
'TV_fw_var',
'TV_fw_args',
'TV_fw_kwargs',
@@ -91,6 +93,8 @@ from .baseobjects import (
TYPE_key_resolver,
TYPE_HoldableTypes,
+ SubProject,
+
HoldableTypes,
)
diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py
index ca17481..7186001 100644
--- a/mesonbuild/interpreterbase/baseobjects.py
+++ b/mesonbuild/interpreterbase/baseobjects.py
@@ -39,6 +39,8 @@ TYPE_kwargs = T.Dict[str, TYPE_var]
TYPE_nkwargs = T.Dict[str, TYPE_nvar]
TYPE_key_resolver = T.Callable[[mparser.BaseNode], str]
+SubProject = T.NewType('SubProject', str)
+
if T.TYPE_CHECKING:
from typing_extensions import Protocol
__T = T.TypeVar('__T', bound=TYPE_var, contravariant=True)
@@ -47,7 +49,7 @@ if T.TYPE_CHECKING:
def __call__(self, other: __T) -> TYPE_var: ...
class InterpreterObject:
- def __init__(self, *, subproject: T.Optional[str] = None) -> None:
+ def __init__(self, *, subproject: T.Optional['SubProject'] = None) -> None:
self.methods: T.Dict[
str,
T.Callable[[T.List[TYPE_var], TYPE_kwargs], TYPE_var]
@@ -63,7 +65,7 @@ class InterpreterObject:
# Current node set during a method call. This can be used as location
# when printing a warning message during a method call.
self.current_node: mparser.BaseNode = None
- self.subproject: str = subproject or ''
+ self.subproject = subproject or SubProject('')
# Some default operators supported by all objects
self.operators.update({
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index c6fcaa0..f104ac6 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -27,8 +27,9 @@ import copy
import typing as T
if T.TYPE_CHECKING:
from .. import mparser
+ from .interpreterbase import SubProject
-def get_callee_args(wrapped_args: T.Sequence[T.Any]) -> T.Tuple['mparser.BaseNode', T.List['TYPE_var'], 'TYPE_kwargs', str]:
+def get_callee_args(wrapped_args: T.Sequence[T.Any]) -> T.Tuple['mparser.BaseNode', T.List['TYPE_var'], 'TYPE_kwargs', 'SubProject']:
# First argument could be InterpreterBase, InterpreterObject or ModuleObject.
# In the case of a ModuleObject it is the 2nd argument (ModuleState) that
# contains the needed information.
@@ -600,7 +601,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
def check_version(target_version: str, feature_version: str) -> bool:
pass
- def use(self, subproject: str) -> None:
+ def use(self, subproject: 'SubProject') -> None:
tv = self.get_target_version(subproject)
# No target version
if tv == '':
@@ -668,7 +669,7 @@ class FeatureCheckBase(metaclass=abc.ABCMeta):
return T.cast(TV_func, wrapped)
@classmethod
- def single_use(cls, feature_name: str, version: str, subproject: str,
+ def single_use(cls, feature_name: str, version: str, subproject: 'SubProject',
extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None:
"""Oneline version that instantiates and calls use()."""
cls(feature_name, version, extra_message, location).use(subproject)
diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py
index 99f6619..bd7d7f9 100644
--- a/mesonbuild/interpreterbase/interpreterbase.py
+++ b/mesonbuild/interpreterbase/interpreterbase.py
@@ -26,6 +26,8 @@ from .baseobjects import (
ObjectHolder,
IterableObject,
+ SubProject,
+
TYPE_var,
TYPE_kwargs,
@@ -73,7 +75,7 @@ FunctionType = T.Dict[
]
class InterpreterBase:
- def __init__(self, source_root: str, subdir: str, subproject: str):
+ def __init__(self, source_root: str, subdir: str, subproject: 'SubProject'):
self.source_root = source_root
self.funcs: FunctionType = {}
self.builtin: T.Dict[str, InterpreterObject] = {}
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 6155c2f..46a4445 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -22,6 +22,7 @@ from . import mlog
from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo, permittedKwargs
if T.TYPE_CHECKING:
from .interpreterbase import TYPE_var, TYPE_kwargs
+ from .interpreterbase import SubProject
from typing_extensions import TypedDict
FuncOptionArgs = TypedDict('FuncOptionArgs', {
'type': str,
@@ -50,7 +51,7 @@ optname_regex = re.compile('[^a-zA-Z0-9_-]')
class OptionInterpreter:
- def __init__(self, subproject: str) -> None:
+ def __init__(self, subproject: 'SubProject') -> None:
self.options: 'coredata.KeyedOptionDictType' = {}
self.subproject = subproject
self.option_types = {'string': self.string_parser,
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 21eb9d6..51632fd 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -35,6 +35,7 @@ from . import WrapMode
from .. import coredata
from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException, windows_proof_rmtree
from ..interpreterbase import FeatureNew
+from ..interpreterbase import SubProject
from .. import mesonlib
if T.TYPE_CHECKING:
@@ -95,7 +96,7 @@ class WrapNotFoundException(WrapException):
class PackageDefinition:
def __init__(self, fname: str, subproject: str = ''):
self.filename = fname
- self.subproject = subproject
+ self.subproject = SubProject(subproject)
self.type = None # type: T.Optional[str]
self.values = {} # type: T.Dict[str, str]
self.provided_deps = {} # type: T.Dict[str, T.Optional[str]]