Skip to content

Commit 650aba4

Browse files
authored
Bug 1441799 - Support number variant keys in BaseNode.equals (#53)
BaseNode.equals sorts order-agnostic fields such as attributes and variants in order to ensure the equality comparison works correctly even if the order of the elements differs. The code used to assume all variant keys were VariantName instances. We need to support numbers as keys as well.
1 parent a673f26 commit 650aba4

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

fluent/syntax/ast.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,12 @@ def equals(self, other, ignored_fields=['span']):
103103
if len(field1) != len(field2):
104104
return False
105105

106-
# These functions are used to sort lists of items for when
107-
# order doesn't matter. Annotations are also lists but they
108-
# can't be keyed on any of their fields reliably.
109-
field_sorting = {
110-
'attributes': lambda elem: elem.id.name,
111-
'variants': lambda elem: elem.key.name,
112-
}
113-
114-
if key in field_sorting:
115-
sorting = field_sorting[key]
116-
field1 = sorted(field1, key=sorting)
117-
field2 = sorted(field2, key=sorting)
106+
# Sort elements of order-agnostic fields to ensure the
107+
# comparison is order-agnostic as well. Annotations should be
108+
# here too but they don't have sorting keys.
109+
if key in ('attributes', 'variants'):
110+
field1 = sorted(field1, key=lambda elem: elem.sorting_key)
111+
field2 = sorted(field2, key=lambda elem: elem.sorting_key)
118112

119113
for elem1, elem2 in zip(field1, field2):
120114
if not scalars_equal(elem1, elem2, ignored_fields):
@@ -255,13 +249,24 @@ def __init__(self, id, value, **kwargs):
255249
self.id = id
256250
self.value = value
257251

252+
@property
253+
def sorting_key(self):
254+
return self.id.name
255+
258256
class Variant(SyntaxNode):
259257
def __init__(self, key, value, default=False, **kwargs):
260258
super(Variant, self).__init__(**kwargs)
261259
self.key = key
262260
self.value = value
263261
self.default = default
264262

263+
@property
264+
def sorting_key(self):
265+
if isinstance(self.key, NumberExpression):
266+
return self.key.value
267+
return self.key.name
268+
269+
265270
class NamedArgument(SyntaxNode):
266271
def __init__(self, name, val, **kwargs):
267272
super(NamedArgument, self).__init__(**kwargs)

tests/syntax/test_equals.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ def test_variants(self):
119119
self.assertTrue(message1.equals(message2))
120120
self.assertTrue(message2.equals(message1))
121121

122+
def test_variants_with_numbers(self):
123+
message1 = self.parse_ftl_entry("""\
124+
foo =
125+
{ $num ->
126+
[1] A
127+
*[b] B
128+
}
129+
""")
130+
message2 = self.parse_ftl_entry("""\
131+
foo =
132+
{ $num ->
133+
*[b] B
134+
[1] A
135+
}
136+
""")
137+
138+
self.assertTrue(message1.equals(message2))
139+
self.assertTrue(message2.equals(message1))
140+
122141

123142
class TestEqualWithSpans(unittest.TestCase):
124143
def test_default_behavior(self):

0 commit comments

Comments
 (0)