summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/mintro.py4
-rw-r--r--mesonbuild/options.py45
-rwxr-xr-xrun_mypy.py1
3 files changed, 32 insertions, 18 deletions
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index cf76b6012..4b65c5aca 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -317,7 +317,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
elif isinstance(opt, options.UserComboOption):
optdict['choices'] = opt.printable_choices()
typestr = 'combo'
- elif isinstance(opt, options.UserIntegerOption):
+ elif isinstance(opt, (options.UserIntegerOption, options.UserUmaskOption)):
typestr = 'integer'
elif isinstance(opt, options.UserStringArrayOption):
typestr = 'array'
@@ -325,7 +325,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
if c:
optdict['choices'] = c
else:
- raise RuntimeError("Unknown option type")
+ raise RuntimeError('Unknown option type: ', repr(type(opt)))
optdict['type'] = typestr
optdict['description'] = opt.description
optlist.append(optdict)
diff --git a/mesonbuild/options.py b/mesonbuild/options.py
index b61babec2..87c31d21c 100644
--- a/mesonbuild/options.py
+++ b/mesonbuild/options.py
@@ -29,7 +29,7 @@ from .mesonlib import (
from . import mlog
if T.TYPE_CHECKING:
- from typing_extensions import TypeAlias, TypedDict
+ from typing_extensions import Literal, TypeAlias, TypedDict
DeprecatedType: TypeAlias = T.Union[bool, str, T.Dict[str, str], T.List[str]]
@@ -320,13 +320,16 @@ class UserBooleanOption(EnumeratedUserOption[bool]):
return False
raise MesonException(f'Option "{self.name}" value {value} is not boolean (true or false).')
-@dataclasses.dataclass
-class UserIntegerOption(UserOption[int]):
- min_value: T.Optional[int] = None
- max_value: T.Optional[int] = None
+class _UserIntegerBase(UserOption[_T]):
+
+ min_value: T.Optional[int]
+ max_value: T.Optional[int]
+
+ if T.TYPE_CHECKING:
+ def toint(self, v: str) -> int: ...
- def __post_init__(self, value_: int) -> None:
+ def __post_init__(self, value_: _T) -> None:
super().__post_init__(value_)
choices: T.List[str] = []
if self.min_value is not None:
@@ -338,16 +341,23 @@ class UserIntegerOption(UserOption[int]):
def printable_choices(self) -> T.Optional[T.List[str]]:
return [self.__choices]
- def validate_value(self, value: T.Any) -> int:
+ def validate_value(self, value: T.Any) -> _T:
if isinstance(value, str):
- value = self.toint(value)
+ value = T.cast('_T', self.toint(value))
if not isinstance(value, int):
raise MesonException(f'Value {value!r} for option "{self.name}" is not an integer.')
if self.min_value is not None and value < self.min_value:
raise MesonException(f'Value {value} for option "{self.name}" is less than minimum value {self.min_value}.')
if self.max_value is not None and value > self.max_value:
raise MesonException(f'Value {value} for option "{self.name}" is more than maximum value {self.max_value}.')
- return value
+ return T.cast('_T', value)
+
+
+@dataclasses.dataclass
+class UserIntegerOption(_UserIntegerBase[int]):
+
+ min_value: T.Optional[int] = None
+ max_value: T.Optional[int] = None
def toint(self, valuestring: str) -> int:
try:
@@ -355,6 +365,7 @@ class UserIntegerOption(UserOption[int]):
except ValueError:
raise MesonException(f'Value string "{valuestring}" for option "{self.name}" is not convertible to an integer.')
+
class OctalInt(int):
# NinjaBackend.get_user_option_args uses str() to converts it to a command line option
# UserUmaskOption.toint() uses int(str, 8) to convert it to an integer
@@ -362,28 +373,30 @@ class OctalInt(int):
def __str__(self) -> str:
return oct(int(self))
+
@dataclasses.dataclass
-class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
+class UserUmaskOption(_UserIntegerBase[T.Union["Literal['preserve']", OctalInt]]):
min_value: T.Optional[int] = dataclasses.field(default=0, init=False)
max_value: T.Optional[int] = dataclasses.field(default=0o777, init=False)
def printable_value(self) -> str:
- if self.value == 'preserve':
- return self.value
- return format(self.value, '04o')
+ if isinstance(self.value, int):
+ return format(self.value, '04o')
+ return self.value
- def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]:
+ def validate_value(self, value: T.Any) -> T.Union[Literal['preserve'], OctalInt]:
if value == 'preserve':
return 'preserve'
return OctalInt(super().validate_value(value))
- def toint(self, valuestring: T.Union[str, OctalInt]) -> int:
+ def toint(self, valuestring: str) -> int:
try:
return int(valuestring, 8)
except ValueError as e:
raise MesonException(f'Invalid mode for option "{self.name}" {e}')
+
@dataclasses.dataclass
class UserComboOption(EnumeratedUserOption[str]):
@@ -581,7 +594,7 @@ class BuiltinOption(T.Generic[_T]):
return '--' + name.replace('_', '-')
def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any:
- if self.opt_type in [UserComboOption, UserIntegerOption]:
+ if self.opt_type in {UserComboOption, UserIntegerOption, UserUmaskOption}:
return self.default
try:
return BUILTIN_DIR_NOPREFIX_OPTIONS[name][prefix]
diff --git a/run_mypy.py b/run_mypy.py
index 9a4e241ec..4f7a6317b 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -79,6 +79,7 @@ modules = [
'mesonbuild/msetup.py',
'mesonbuild/mtest.py',
'mesonbuild/optinterpreter.py',
+ 'mesonbuild/options.py',
'mesonbuild/programs.py',
]
additional = [