summaryrefslogtreecommitdiff
path: root/mesonbuild/coredata.py
diff options
context:
space:
mode:
authorJohn Ericson <git@JohnEricson.me>2019-05-12 12:38:11 -0400
committerJussi Pakkanen <jpakkane@gmail.com>2019-05-15 14:21:47 +0300
commit4030e7cb7ad54dd2df0686f41459fc6293c8284f (patch)
treee7366f78785419ad7d301fb68bc4b508fba9079e /mesonbuild/coredata.py
parent7b8ef78bc0002d0327626c6218b793f87c2a5eb8 (diff)
downloadmeson-4030e7cb7ad54dd2df0686f41459fc6293c8284f.tar.gz
UserOption no longer has a name field.
This avoids the duplication where the option is stored in a dict at its name, and also contains its own name. In general, the maxim in programming is things shouldn't know their own name, so removed the name field just leaving the option's position in the dictionary as its name.
Diffstat (limited to 'mesonbuild/coredata.py')
-rw-r--r--mesonbuild/coredata.py90
1 files changed, 47 insertions, 43 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 183b333aa..34adad3e7 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -26,17 +26,19 @@ from .wrap import WrapMode
import ast
import argparse
import configparser
-from typing import Optional, Any, TypeVar, Generic, Type, List
+from typing import Optional, Any, TypeVar, Generic, Type, List, Union
version = '0.50.999'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
default_yielding = False
-class UserOption:
- def __init__(self, name, description, choices, yielding):
+# Can't bind this near the class method it seems, sadly.
+_T = TypeVar('_T')
+
+class UserOption(Generic[_T]):
+ def __init__(self, description, choices, yielding):
super().__init__()
- self.name = name
self.choices = choices
self.description = description
if yielding is None:
@@ -51,31 +53,31 @@ class UserOption:
# Check that the input is a valid value and return the
# "cleaned" or "native" version. For example the Boolean
# option could take the string "true" and return True.
- def validate_value(self, value):
+ def validate_value(self, value: Any) -> _T:
raise RuntimeError('Derived option class did not override validate_value.')
def set_value(self, newvalue):
self.value = self.validate_value(newvalue)
-class UserStringOption(UserOption):
- def __init__(self, name, description, value, choices=None, yielding=None):
- super().__init__(name, description, choices, yielding)
+class UserStringOption(UserOption[str]):
+ def __init__(self, description, value, choices=None, yielding=None):
+ super().__init__(description, choices, yielding)
self.set_value(value)
def validate_value(self, value):
if not isinstance(value, str):
- raise MesonException('Value "%s" for string option "%s" is not a string.' % (str(value), self.name))
+ raise MesonException('Value "%s" for string option is not a string.' % str(value))
return value
-class UserBooleanOption(UserOption):
- def __init__(self, name, description, value, yielding=None):
- super().__init__(name, description, [True, False], yielding)
+class UserBooleanOption(UserOption[bool]):
+ def __init__(self, description, value, yielding=None):
+ super().__init__(description, [True, False], yielding)
self.set_value(value)
- def __bool__(self):
+ def __bool__(self) -> bool:
return self.value
- def validate_value(self, value):
+ def validate_value(self, value) -> bool:
if isinstance(value, bool):
return value
if value.lower() == 'true':
@@ -84,9 +86,9 @@ class UserBooleanOption(UserOption):
return False
raise MesonException('Value %s is not boolean (true or false).' % value)
-class UserIntegerOption(UserOption):
- def __init__(self, name, description, min_value, max_value, value, yielding=None):
- super().__init__(name, description, [True, False], yielding)
+class UserIntegerOption(UserOption[int]):
+ def __init__(self, description, min_value, max_value, value, yielding=None):
+ super().__init__(description, [True, False], yielding)
self.min_value = min_value
self.max_value = max_value
self.set_value(value)
@@ -97,7 +99,7 @@ class UserIntegerOption(UserOption):
c.append('<=' + str(max_value))
self.choices = ', '.join(c)
- def validate_value(self, value):
+ def validate_value(self, value) -> int:
if isinstance(value, str):
value = self.toint(value)
if not isinstance(value, int):
@@ -108,15 +110,15 @@ class UserIntegerOption(UserOption):
raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value))
return value
- def toint(self, valuestring):
+ def toint(self, valuestring) -> int:
try:
return int(valuestring)
except ValueError:
raise MesonException('Value string "%s" is not convertable to an integer.' % valuestring)
-class UserUmaskOption(UserIntegerOption):
- def __init__(self, name, description, value, yielding=None):
- super().__init__(name, description, 0, 0o777, value, yielding)
+class UserUmaskOption(UserIntegerOption, UserOption[Union[str, int]]):
+ def __init__(self, description, value, yielding=None):
+ super().__init__(description, 0, 0o777, value, yielding)
self.choices = ['preserve', '0000-0777']
def printable_value(self):
@@ -135,9 +137,9 @@ class UserUmaskOption(UserIntegerOption):
except ValueError as e:
raise MesonException('Invalid mode: {}'.format(e))
-class UserComboOption(UserOption):
- def __init__(self, name, description, choices, value, yielding=None):
- super().__init__(name, description, choices, yielding)
+class UserComboOption(UserOption[str]):
+ def __init__(self, description, choices: List[str], value, yielding=None):
+ super().__init__(description, choices, yielding)
if not isinstance(self.choices, list):
raise MesonException('Combo choices must be an array.')
for i in self.choices:
@@ -148,17 +150,17 @@ class UserComboOption(UserOption):
def validate_value(self, value):
if value not in self.choices:
optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices])
- raise MesonException('Value "%s" for combo option "%s" is not one of the choices. Possible choices are: %s.' % (value, self.name, optionsstring))
+ raise MesonException('Value "%s" for combo option is not one of the choices. Possible choices are: %s.' % (value, optionsstring))
return value
-class UserArrayOption(UserOption):
- def __init__(self, name, description, value, shlex_split=False, user_input=False, allow_dups=False, **kwargs):
- super().__init__(name, description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
+class UserArrayOption(UserOption[List[str]]):
+ def __init__(self, description, value, shlex_split=False, user_input=False, allow_dups=False, **kwargs):
+ super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
self.shlex_split = shlex_split
self.allow_dups = allow_dups
self.value = self.validate_value(value, user_input=user_input)
- def validate_value(self, value, user_input=True):
+ def validate_value(self, value, user_input=True) -> List[str]:
# User input is for options defined on the command line (via -D
# options). Users can put their input in as a comma separated
# string, but for defining options in meson_options.txt the format
@@ -182,8 +184,8 @@ class UserArrayOption(UserOption):
raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue)))
if not self.allow_dups and len(set(newvalue)) != len(newvalue):
- msg = 'Duplicated values in array option "%s" is deprecated. ' \
- 'This will become a hard error in the future.' % (self.name)
+ msg = 'Duplicated values in array option is deprecated. ' \
+ 'This will become a hard error in the future.'
mlog.deprecation(msg)
for i in newvalue:
if not isinstance(i, str):
@@ -199,8 +201,8 @@ class UserArrayOption(UserOption):
class UserFeatureOption(UserComboOption):
static_choices = ['enabled', 'disabled', 'auto']
- def __init__(self, name, description, value, yielding=None):
- super().__init__(name, description, self.static_choices, value, yielding)
+ def __init__(self, description, value, yielding=None):
+ super().__init__(description, self.static_choices, value, yielding)
def is_enabled(self):
return self.value == 'enabled'
@@ -334,22 +336,20 @@ class CoreData:
# Create builtin options with default values
self.builtins = {}
for key, opt in builtin_options.items():
- self.builtins[key] = opt.init_option(key)
+ self.builtins[key] = opt.init_option()
if opt.separate_cross:
- self.builtins['cross_' + key] = opt.init_option(key)
+ self.builtins['cross_' + key] = opt.init_option()
def init_backend_options(self, backend_name):
if backend_name == 'ninja':
self.backend_options['backend_max_links'] = \
UserIntegerOption(
- 'backend_max_links',
'Maximum number of linker processes to run or 0 for no '
'limit',
0, None, 0)
elif backend_name.startswith('vs'):
self.backend_options['backend_startup_project'] = \
UserStringOption(
- 'backend_startup_project',
'Default project to execute in Visual Studio',
'')
@@ -433,7 +433,11 @@ class CoreData:
for opts in self.get_all_options():
if option_name in opts:
opt = opts[option_name]
- return opt.validate_value(override_value)
+ try:
+ return opt.validate_value(override_value)
+ except MesonException as e:
+ raise type(e)(('Validation failed for option %s: ' % option_name) + str(e)) \
+ .with_traceback(sys.exc_into()[2])
raise MesonException('Tried to validate unknown option %s.' % option_name)
def get_external_args(self, for_machine: MachineChoice, lang):
@@ -695,9 +699,9 @@ def parse_cmd_line_options(args):
delattr(args, name)
-_U = TypeVar('_U', bound=UserOption)
+_U = TypeVar('_U', bound=UserOption[_T])
-class BuiltinOption(Generic[_U]):
+class BuiltinOption(Generic[_T, _U]):
"""Class for a builtin option type.
@@ -713,12 +717,12 @@ class BuiltinOption(Generic[_U]):
self.yielding = yielding
self.separate_cross = separate_cross
- def init_option(self, name: str) -> _U:
+ def init_option(self) -> _U:
"""Create an instance of opt_type and return it."""
keywords = {'yielding': self.yielding, 'value': self.default}
if self.choices:
keywords['choices'] = self.choices
- return self.opt_type(name, self.description, **keywords)
+ return self.opt_type(self.description, **keywords)
def _argparse_action(self) -> Optional[str]:
if self.default is True: