Skip to content

Commit b402643

Browse files
committed
Factor flatten_elements and prune_text_elements out of CONCAT and REPLACE
1 parent 3d791a7 commit b402643

File tree

1 file changed

+40
-53
lines changed

1 file changed

+40
-53
lines changed

fluent/migrate/transforms.py

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,38 @@ class Transform(FTL.BaseNode):
9090
def __call__(self, ctx):
9191
raise NotImplementedError
9292

93+
@staticmethod
94+
def flatten_elements(elements):
95+
'''Flatten a list of FTL nodes into valid Pattern's elements'''
96+
flattened = []
97+
for element in elements:
98+
if isinstance(element, FTL.Pattern):
99+
flattened.extend(element.elements)
100+
elif isinstance(element, FTL.PatternElement):
101+
flattened.append(element)
102+
elif isinstance(element, FTL.Expression):
103+
flattened.append(FTL.Placeable(element))
104+
else:
105+
raise RuntimeError(
106+
'Expected Pattern, PatternElement or Expression')
107+
return flattened
108+
109+
@staticmethod
110+
def prune_text_elements(elements):
111+
'''Join adjacent TextElements and remove empty ones'''
112+
pruned = []
113+
# Group elements in contiguous sequences of the same type.
114+
for elem_type, elems in itertools.groupby(elements, key=type):
115+
if elem_type is FTL.TextElement:
116+
# Join adjacent TextElements.
117+
text = FTL.TextElement(''.join(elem.value for elem in elems))
118+
# And remove empty ones.
119+
if len(text.value) > 0:
120+
pruned.append(text)
121+
else:
122+
pruned.extend(elems)
123+
return pruned
124+
93125

94126
class Source(Transform):
95127
"""Declare the source translation to be migrated with other transforms.
@@ -157,7 +189,7 @@ def __call__(self, ctx):
157189

158190
# A list of PatternElements built from the legacy translation and the
159191
# FTL replacements. It may contain empty or adjacent TextElements.
160-
parts = []
192+
elements = []
161193
tail = self.value
162194

163195
# Convert original placeables and text into FTL Nodes. For each
@@ -166,33 +198,14 @@ def __call__(self, ctx):
166198
# the placeable will be replaced with its replacement.
167199
for key in keys_in_order:
168200
before, key, tail = tail.partition(key)
169-
170-
# The replacement value can be of different types.
171-
replacement = replacements[key]
172-
if isinstance(replacement, FTL.Pattern):
173-
repl_elements = replacement.elements
174-
elif isinstance(replacement, FTL.PatternElement):
175-
repl_elements = [replacement]
176-
elif isinstance(replacement, FTL.Expression):
177-
repl_elements = [FTL.Placeable(replacement)]
178-
179-
parts.append(FTL.TextElement(before))
180-
parts.extend(repl_elements)
201+
elements.append(FTL.TextElement(before))
202+
elements.append(replacements[key])
181203

182204
# Dont' forget about the tail after the loop ends.
183-
parts.append(FTL.TextElement(tail))
184-
185-
# Join adjacent TextElements.
186-
elements = []
187-
for elem_type, elems in itertools.groupby(parts, key=type):
188-
if elem_type is FTL.TextElement:
189-
text = FTL.TextElement(''.join(elem.value for elem in elems))
190-
# And remove empty ones.
191-
if len(text.value) > 0:
192-
elements.append(text)
193-
else:
194-
elements.extend(elems)
205+
elements.append(FTL.TextElement(tail))
195206

207+
elements = self.flatten_elements(elements)
208+
elements = self.prune_text_elements(elements)
196209
return FTL.Pattern(elements)
197210

198211

@@ -270,34 +283,8 @@ def __init__(self, *patterns):
270283
self.patterns = list(patterns)
271284

272285
def __call__(self, ctx):
273-
# Flatten the list of patterns of which each has a list of elements.
274-
def concat_elements(acc, cur):
275-
if isinstance(cur, FTL.Pattern):
276-
acc.extend(cur.elements)
277-
return acc
278-
elif (isinstance(cur, FTL.TextElement) or
279-
isinstance(cur, FTL.Placeable)):
280-
acc.append(cur)
281-
return acc
282-
283-
raise RuntimeError(
284-
'CONCAT accepts FTL Patterns, TextElements and Placeables.'
285-
)
286-
287-
# Merge adjecent `FTL.TextElement` nodes.
288-
def merge_adjecent_text(acc, cur):
289-
if type(cur) == FTL.TextElement and len(acc):
290-
last = acc[-1]
291-
if type(last) == FTL.TextElement:
292-
last.value += cur.value
293-
else:
294-
acc.append(cur)
295-
else:
296-
acc.append(cur)
297-
return acc
298-
299-
elements = reduce(concat_elements, self.patterns, [])
300-
elements = reduce(merge_adjecent_text, elements, [])
286+
elements = self.flatten_elements(self.patterns)
287+
elements = self.prune_text_elements(elements)
301288
return FTL.Pattern(elements)
302289

303290
def traverse(self, fun):

0 commit comments

Comments
 (0)