diff options
| author | Jouke Witteveen <j.witteveen@gmail.com> | 2024-01-26 13:44:19 +0100 |
|---|---|---|
| committer | Jussi Pakkanen <jpakkane@gmail.com> | 2024-02-26 23:30:39 +0200 |
| commit | f013a688980a6014cab03386910d1c464a4e4a8f (patch) | |
| tree | cb2526142048d4275b2bcf633512777131c90374 | |
| parent | fb72a8ecdb9d571f15163454e4f513ded0b28cc5 (diff) | |
| download | meson-f013a688980a6014cab03386910d1c464a4e4a8f.tar.gz | |
rewriter: allow setting values regardless of the previous type
Alterations to kwargs come in two flavors:
1. Remove/replace values (delete/set)
2. Modify values (add/remove)
Only for the second flavor do we care about the type of any existing
value.
| -rw-r--r-- | mesonbuild/rewriter.py | 188 |
1 files changed, 101 insertions, 87 deletions
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 434b21974..fd5413ac1 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -98,17 +98,23 @@ def _symbol(val: str) -> SymbolNode: class MTypeBase: def __init__(self, node: T.Optional[BaseNode] = None): if node is None: - self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state) + self.node = self.new_node() else: self.node = node self.node_type = None - for i in self.supported_nodes(): # lgtm [py/init-calls-subclass] (listing nodes does not depend on base class state) + for i in self.supported_nodes(): if isinstance(self.node, i): self.node_type = i - def _new_node(self): + @classmethod + def new_node(cls, value=None): # Overwrite in derived class - raise RewriterException('Internal error: _new_node of MTypeBase was called') + raise RewriterException('Internal error: new_node of MTypeBase was called') + + @classmethod + def supported_nodes(cls): + # Overwrite in derived class + return [] def can_modify(self): return self.node_type is not None @@ -116,14 +122,6 @@ class MTypeBase: def get_node(self): return self.node - def supported_nodes(self): - # Overwrite in derived class - return [] - - def set_value(self, value): - # Overwrite in derived class - mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping') - def add_value(self, value): # Overwrite in derived class mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping') @@ -140,63 +138,74 @@ class MTypeStr(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return StringNode(Token('', '', 0, 0, 0, None, '')) + @classmethod + def new_node(cls, value=None): + if value is None: + value = '' + return StringNode(Token('', '', 0, 0, 0, None, str(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [StringNode] - def set_value(self, value): - self.node.value = str(value) - class MTypeBool(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return BooleanNode(Token('', '', 0, 0, 0, None, False)) + @classmethod + def new_node(cls, value=None): + return BooleanNode(Token('', '', 0, 0, 0, None, bool(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [BooleanNode] - def set_value(self, value): - self.node.value = bool(value) - class MTypeID(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return IdNode(Token('', '', 0, 0, 0, None, '')) + @classmethod + def new_node(cls, value=None): + if value is None: + value = '' + return IdNode(Token('', '', 0, 0, 0, None, str(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [IdNode] - def set_value(self, value): - self.node.value = str(value) - class MTypeList(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']')) - - def _new_element_node(self, value): + @classmethod + def new_node(cls, value=None): + if value is None: + value = [] + elif not isinstance(value, list): + return cls._new_element_node(value) + args = ArgumentNode(Token('', '', 0, 0, 0, None, '')) + args.arguments = [cls._new_element_node(i) for i in value] + return ArrayNode(_symbol('['), args, _symbol(']')) + + @classmethod + def _new_element_node(cls, value): # Overwrite in derived class raise RewriterException('Internal error: _new_element_node of MTypeList was called') def _ensure_array_node(self): if not isinstance(self.node, ArrayNode): tmp = self.node - self.node = self._new_node() - self.node.args.arguments += [tmp] + self.node = self.new_node() + self.node.args.arguments = [tmp] - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: # Overwrite in derived class return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: # Overwrite in derived class return False @@ -206,20 +215,14 @@ class MTypeList(MTypeBase): return self.node.args.arguments[0] return self.node - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): # Overwrite in derived class return [] - def supported_nodes(self): - return [ArrayNode] + self.supported_element_nodes() - - def set_value(self, value): - if not isinstance(value, list): - value = [value] - self._ensure_array_node() - self.node.args.arguments = [] # Remove all current nodes - for i in value: - self.node.args.arguments += [self._new_element_node(i)] + @classmethod + def supported_nodes(cls): + return [ArrayNode] + cls.supported_element_nodes() def add_value(self, value): if not isinstance(value, list): @@ -254,40 +257,48 @@ class MTypeStrList(MTypeList): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_element_node(self, value): + @classmethod + def _new_element_node(cls, value): return StringNode(Token('', '', 0, 0, 0, None, str(value))) - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: if isinstance(node, BaseStringNode): return node.value == value return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): return [StringNode] class MTypeIDList(MTypeList): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_element_node(self, value): + @classmethod + def _new_element_node(cls, value): return IdNode(Token('', '', 0, 0, 0, None, str(value))) - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: if isinstance(node, IdNode): return node.value == value return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): return [IdNode] rewriter_keys = { @@ -548,39 +559,42 @@ class Rewriter: self.handle_error() continue - # Remove the key from the kwargs if cmd['operation'] == 'delete': - if key in arg_node.kwargs: - mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') - del arg_node.kwargs[key] - num_changed += 1 - else: + # Remove the key from the kwargs + if key not in arg_node.kwargs: mlog.log(' -- Key', mlog.bold(key), 'is already deleted') - continue + continue + mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') + del arg_node.kwargs[key] + elif cmd['operation'] == 'set': + # Replace the key from the kwargs + mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(str(val))) + arg_node.kwargs[key] = kwargs_def[key].new_node(val) + else: + # Modify the value from the kwargs + + if key not in arg_node.kwargs: + arg_node.kwargs[key] = None + modifier = kwargs_def[key](arg_node.kwargs[key]) + if not modifier.can_modify(): + mlog.log(' -- Skipping', mlog.bold(key), 'because it is too complex to modify') + continue + + # Apply the operation + val_str = str(val) + if cmd['operation'] == 'add': + mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) + modifier.add_value(val) + elif cmd['operation'] == 'remove': + mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_value(val) + elif cmd['operation'] == 'remove_regex': + mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_regex(val) + + # Write back the result + arg_node.kwargs[key] = modifier.get_node() - if key not in arg_node.kwargs: - arg_node.kwargs[key] = None - modifier = kwargs_def[key](arg_node.kwargs[key]) - if not modifier.can_modify(): - mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify') - - # Apply the operation - val_str = str(val) - if cmd['operation'] == 'set': - mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str)) - modifier.set_value(val) - elif cmd['operation'] == 'add': - mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) - modifier.add_value(val) - elif cmd['operation'] == 'remove': - mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifier.remove_value(val) - elif cmd['operation'] == 'remove_regex': - mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifier.remove_regex(val) - - # Write back the result - arg_node.kwargs[key] = modifier.get_node() num_changed += 1 # Convert the keys back to IdNode's |
