Skip to content

Commit f013a68

Browse files
joukewitteveenjpakkane
authored andcommitted
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.
1 parent fb72a8e commit f013a68

File tree

1 file changed

+101
-87
lines changed

1 file changed

+101
-87
lines changed

mesonbuild/rewriter.py

Lines changed: 101 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -98,32 +98,30 @@ def _symbol(val: str) -> SymbolNode:
9898
class MTypeBase:
9999
def __init__(self, node: T.Optional[BaseNode] = None):
100100
if node is None:
101-
self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state)
101+
self.node = self.new_node()
102102
else:
103103
self.node = node
104104
self.node_type = None
105-
for i in self.supported_nodes(): # lgtm [py/init-calls-subclass] (listing nodes does not depend on base class state)
105+
for i in self.supported_nodes():
106106
if isinstance(self.node, i):
107107
self.node_type = i
108108

109-
def _new_node(self):
109+
@classmethod
110+
def new_node(cls, value=None):
110111
# Overwrite in derived class
111-
raise RewriterException('Internal error: _new_node of MTypeBase was called')
112+
raise RewriterException('Internal error: new_node of MTypeBase was called')
113+
114+
@classmethod
115+
def supported_nodes(cls):
116+
# Overwrite in derived class
117+
return []
112118

113119
def can_modify(self):
114120
return self.node_type is not None
115121

116122
def get_node(self):
117123
return self.node
118124

119-
def supported_nodes(self):
120-
# Overwrite in derived class
121-
return []
122-
123-
def set_value(self, value):
124-
# Overwrite in derived class
125-
mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping')
126-
127125
def add_value(self, value):
128126
# Overwrite in derived class
129127
mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping')
@@ -140,63 +138,74 @@ class MTypeStr(MTypeBase):
140138
def __init__(self, node: T.Optional[BaseNode] = None):
141139
super().__init__(node)
142140

143-
def _new_node(self):
144-
return StringNode(Token('', '', 0, 0, 0, None, ''))
141+
@classmethod
142+
def new_node(cls, value=None):
143+
if value is None:
144+
value = ''
145+
return StringNode(Token('', '', 0, 0, 0, None, str(value)))
145146

146-
def supported_nodes(self):
147+
@classmethod
148+
def supported_nodes(cls):
147149
return [StringNode]
148150

149-
def set_value(self, value):
150-
self.node.value = str(value)
151-
152151
class MTypeBool(MTypeBase):
153152
def __init__(self, node: T.Optional[BaseNode] = None):
154153
super().__init__(node)
155154

156-
def _new_node(self):
157-
return BooleanNode(Token('', '', 0, 0, 0, None, False))
155+
@classmethod
156+
def new_node(cls, value=None):
157+
return BooleanNode(Token('', '', 0, 0, 0, None, bool(value)))
158158

159-
def supported_nodes(self):
159+
@classmethod
160+
def supported_nodes(cls):
160161
return [BooleanNode]
161162

162-
def set_value(self, value):
163-
self.node.value = bool(value)
164-
165163
class MTypeID(MTypeBase):
166164
def __init__(self, node: T.Optional[BaseNode] = None):
167165
super().__init__(node)
168166

169-
def _new_node(self):
170-
return IdNode(Token('', '', 0, 0, 0, None, ''))
167+
@classmethod
168+
def new_node(cls, value=None):
169+
if value is None:
170+
value = ''
171+
return IdNode(Token('', '', 0, 0, 0, None, str(value)))
171172

172-
def supported_nodes(self):
173+
@classmethod
174+
def supported_nodes(cls):
173175
return [IdNode]
174176

175-
def set_value(self, value):
176-
self.node.value = str(value)
177-
178177
class MTypeList(MTypeBase):
179178
def __init__(self, node: T.Optional[BaseNode] = None):
180179
super().__init__(node)
181180

182-
def _new_node(self):
183-
return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']'))
184-
185-
def _new_element_node(self, value):
181+
@classmethod
182+
def new_node(cls, value=None):
183+
if value is None:
184+
value = []
185+
elif not isinstance(value, list):
186+
return cls._new_element_node(value)
187+
args = ArgumentNode(Token('', '', 0, 0, 0, None, ''))
188+
args.arguments = [cls._new_element_node(i) for i in value]
189+
return ArrayNode(_symbol('['), args, _symbol(']'))
190+
191+
@classmethod
192+
def _new_element_node(cls, value):
186193
# Overwrite in derived class
187194
raise RewriterException('Internal error: _new_element_node of MTypeList was called')
188195

189196
def _ensure_array_node(self):
190197
if not isinstance(self.node, ArrayNode):
191198
tmp = self.node
192-
self.node = self._new_node()
193-
self.node.args.arguments += [tmp]
199+
self.node = self.new_node()
200+
self.node.args.arguments = [tmp]
194201

195-
def _check_is_equal(self, node, value) -> bool:
202+
@staticmethod
203+
def _check_is_equal(node, value) -> bool:
196204
# Overwrite in derived class
197205
return False
198206

199-
def _check_regex_matches(self, node, regex: str) -> bool:
207+
@staticmethod
208+
def _check_regex_matches(node, regex: str) -> bool:
200209
# Overwrite in derived class
201210
return False
202211

@@ -206,20 +215,14 @@ def get_node(self):
206215
return self.node.args.arguments[0]
207216
return self.node
208217

209-
def supported_element_nodes(self):
218+
@classmethod
219+
def supported_element_nodes(cls):
210220
# Overwrite in derived class
211221
return []
212222

213-
def supported_nodes(self):
214-
return [ArrayNode] + self.supported_element_nodes()
215-
216-
def set_value(self, value):
217-
if not isinstance(value, list):
218-
value = [value]
219-
self._ensure_array_node()
220-
self.node.args.arguments = [] # Remove all current nodes
221-
for i in value:
222-
self.node.args.arguments += [self._new_element_node(i)]
223+
@classmethod
224+
def supported_nodes(cls):
225+
return [ArrayNode] + cls.supported_element_nodes()
223226

224227
def add_value(self, value):
225228
if not isinstance(value, list):
@@ -254,40 +257,48 @@ class MTypeStrList(MTypeList):
254257
def __init__(self, node: T.Optional[BaseNode] = None):
255258
super().__init__(node)
256259

257-
def _new_element_node(self, value):
260+
@classmethod
261+
def _new_element_node(cls, value):
258262
return StringNode(Token('', '', 0, 0, 0, None, str(value)))
259263

260-
def _check_is_equal(self, node, value) -> bool:
264+
@staticmethod
265+
def _check_is_equal(node, value) -> bool:
261266
if isinstance(node, BaseStringNode):
262267
return node.value == value
263268
return False
264269

265-
def _check_regex_matches(self, node, regex: str) -> bool:
270+
@staticmethod
271+
def _check_regex_matches(node, regex: str) -> bool:
266272
if isinstance(node, BaseStringNode):
267273
return re.match(regex, node.value) is not None
268274
return False
269275

270-
def supported_element_nodes(self):
276+
@classmethod
277+
def supported_element_nodes(cls):
271278
return [StringNode]
272279

273280
class MTypeIDList(MTypeList):
274281
def __init__(self, node: T.Optional[BaseNode] = None):
275282
super().__init__(node)
276283

277-
def _new_element_node(self, value):
284+
@classmethod
285+
def _new_element_node(cls, value):
278286
return IdNode(Token('', '', 0, 0, 0, None, str(value)))
279287

280-
def _check_is_equal(self, node, value) -> bool:
288+
@staticmethod
289+
def _check_is_equal(node, value) -> bool:
281290
if isinstance(node, IdNode):
282291
return node.value == value
283292
return False
284293

285-
def _check_regex_matches(self, node, regex: str) -> bool:
294+
@staticmethod
295+
def _check_regex_matches(node, regex: str) -> bool:
286296
if isinstance(node, BaseStringNode):
287297
return re.match(regex, node.value) is not None
288298
return False
289299

290-
def supported_element_nodes(self):
300+
@classmethod
301+
def supported_element_nodes(cls):
291302
return [IdNode]
292303

293304
rewriter_keys = {
@@ -548,39 +559,42 @@ def process_kwargs(self, cmd):
548559
self.handle_error()
549560
continue
550561

551-
# Remove the key from the kwargs
552562
if cmd['operation'] == 'delete':
553-
if key in arg_node.kwargs:
554-
mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs')
555-
del arg_node.kwargs[key]
556-
num_changed += 1
557-
else:
563+
# Remove the key from the kwargs
564+
if key not in arg_node.kwargs:
558565
mlog.log(' -- Key', mlog.bold(key), 'is already deleted')
559-
continue
566+
continue
567+
mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs')
568+
del arg_node.kwargs[key]
569+
elif cmd['operation'] == 'set':
570+
# Replace the key from the kwargs
571+
mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(str(val)))
572+
arg_node.kwargs[key] = kwargs_def[key].new_node(val)
573+
else:
574+
# Modify the value from the kwargs
575+
576+
if key not in arg_node.kwargs:
577+
arg_node.kwargs[key] = None
578+
modifier = kwargs_def[key](arg_node.kwargs[key])
579+
if not modifier.can_modify():
580+
mlog.log(' -- Skipping', mlog.bold(key), 'because it is too complex to modify')
581+
continue
582+
583+
# Apply the operation
584+
val_str = str(val)
585+
if cmd['operation'] == 'add':
586+
mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key))
587+
modifier.add_value(val)
588+
elif cmd['operation'] == 'remove':
589+
mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key))
590+
modifier.remove_value(val)
591+
elif cmd['operation'] == 'remove_regex':
592+
mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key))
593+
modifier.remove_regex(val)
594+
595+
# Write back the result
596+
arg_node.kwargs[key] = modifier.get_node()
560597

561-
if key not in arg_node.kwargs:
562-
arg_node.kwargs[key] = None
563-
modifier = kwargs_def[key](arg_node.kwargs[key])
564-
if not modifier.can_modify():
565-
mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify')
566-
567-
# Apply the operation
568-
val_str = str(val)
569-
if cmd['operation'] == 'set':
570-
mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str))
571-
modifier.set_value(val)
572-
elif cmd['operation'] == 'add':
573-
mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key))
574-
modifier.add_value(val)
575-
elif cmd['operation'] == 'remove':
576-
mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key))
577-
modifier.remove_value(val)
578-
elif cmd['operation'] == 'remove_regex':
579-
mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key))
580-
modifier.remove_regex(val)
581-
582-
# Write back the result
583-
arg_node.kwargs[key] = modifier.get_node()
584598
num_changed += 1
585599

586600
# Convert the keys back to IdNode's

0 commit comments

Comments
 (0)