Skip to content

Commit c27cde5

Browse files
committed
Remove deprecated BaseNode.traverse
In #97, we deprecated `BaseNode.traverse`. It's now time to remove it. The reason it was still around is mostly for a niche in performance, but dedicated iterators are probably the way to go for that niche. That's what fluent.runtime does, for example.
1 parent d421ce1 commit c27cde5

File tree

4 files changed

+5
-112
lines changed

4 files changed

+5
-112
lines changed

fluent.syntax/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## fluent.syntax 0.18 (not released)
4+
5+
- Documentation is now on https://projectfluent.org/python-fluent/fluent.syntax/.
6+
- Removal of deprecated `BaseNode.traverse` method.
7+
38
## fluent.syntax 0.17 (September 10, 2019)
49

510
- Parser fix for whitespace before call arguments.

fluent.syntax/fluent/syntax/ast.py

-27
Original file line numberDiff line numberDiff line change
@@ -112,33 +112,6 @@ class BaseNode(object):
112112
Annotation. Implements __str__, to_json and traverse.
113113
"""
114114

115-
def traverse(self, fun):
116-
"""DEPRECATED. Please use Visitor or Transformer.
117-
118-
Postorder-traverse this node and apply `fun` to all child nodes.
119-
120-
Traverse this node depth-first applying `fun` to subnodes and leaves.
121-
Children are processed before parents (postorder traversal).
122-
123-
Return a new instance of the node.
124-
"""
125-
126-
def visit(value):
127-
"""Call `fun` on `value` and its descendants."""
128-
if isinstance(value, BaseNode):
129-
return value.traverse(fun)
130-
if isinstance(value, list):
131-
return fun(list(map(visit, value)))
132-
else:
133-
return fun(value)
134-
135-
# Use all attributes found on the node as kwargs to the constructor.
136-
kwargs = vars(self).items()
137-
node = self.__class__(
138-
**{name: visit(value) for name, value in kwargs})
139-
140-
return fun(node)
141-
142115
def clone(self):
143116
"""Create a deep clone of the current node."""
144117
def visit(value):

fluent.syntax/tests/syntax/test_equals.py

-10
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
from fluent.syntax.parser import FluentParser
66

77

8-
def identity(node):
9-
return node
10-
11-
128
class TestEntryEqualToSelf(unittest.TestCase):
139
def setUp(self):
1410
self.parser = FluentParser()
@@ -22,7 +18,6 @@ def test_same_simple_message(self):
2218
""")
2319

2420
self.assertTrue(message1.equals(message1))
25-
self.assertTrue(message1.equals(message1.traverse(identity)))
2621
self.assertTrue(message1.equals(message1.clone()))
2722

2823
def test_same_selector_message(self):
@@ -38,7 +33,6 @@ def test_same_selector_message(self):
3833
""")
3934

4035
self.assertTrue(message1.equals(message1))
41-
self.assertTrue(message1.equals(message1.traverse(identity)))
4236
self.assertTrue(message1.equals(message1.clone()))
4337

4438
def test_same_complex_placeable_message(self):
@@ -47,7 +41,6 @@ def test_same_complex_placeable_message(self):
4741
""")
4842

4943
self.assertTrue(message1.equals(message1))
50-
self.assertTrue(message1.equals(message1.traverse(identity)))
5144
self.assertTrue(message1.equals(message1.clone()))
5245

5346
def test_same_message_with_attribute(self):
@@ -57,7 +50,6 @@ def test_same_message_with_attribute(self):
5750
""")
5851

5952
self.assertTrue(message1.equals(message1))
60-
self.assertTrue(message1.equals(message1.traverse(identity)))
6153
self.assertTrue(message1.equals(message1.clone()))
6254

6355
def test_same_message_with_attributes(self):
@@ -68,7 +60,6 @@ def test_same_message_with_attributes(self):
6860
""")
6961

7062
self.assertTrue(message1.equals(message1))
71-
self.assertTrue(message1.equals(message1.traverse(identity)))
7263
self.assertTrue(message1.equals(message1.clone()))
7364

7465
def test_same_junk(self):
@@ -77,7 +68,6 @@ def test_same_junk(self):
7768
""")
7869

7970
self.assertTrue(message1.equals(message1))
80-
self.assertTrue(message1.equals(message1.traverse(identity)))
8171
self.assertTrue(message1.equals(message1.clone()))
8272

8373

fluent.syntax/tests/syntax/test_visitor.py

-75
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
from __future__ import unicode_literals
22

3-
import codecs
43
from collections import defaultdict
5-
import os
64
import unittest
7-
import timeit
85

96
from fluent.syntax.parser import FluentParser
107
from fluent.syntax import ast
@@ -121,75 +118,3 @@ def visit_TextElement(self, node):
121118
"""Perform find and replace on text values only"""
122119
node.value = node.value.replace(self.before, self.after)
123120
return node
124-
125-
126-
class TestPerf(unittest.TestCase):
127-
def setUp(self):
128-
parser = FluentParser()
129-
workload = os.path.join(
130-
os.path.dirname(__file__), 'fixtures_perf', 'workload-low.ftl'
131-
)
132-
with codecs.open(workload, encoding='utf-8') as f:
133-
self.resource = parser.parse(f.read())
134-
135-
def test_traverse(self):
136-
counter = WordCounter()
137-
self.resource.traverse(counter)
138-
self.assertEqual(counter.word_count, 277)
139-
140-
def test_visitor(self):
141-
counter = VisitorCounter()
142-
counter.visit(self.resource)
143-
self.assertEqual(counter.word_count, 277)
144-
145-
def test_edit_traverse(self):
146-
edited = self.resource.traverse(ReplaceText('Tab', 'Reiter'))
147-
self.assertEqual(
148-
edited.body[4].attributes[0].value.elements[0].value,
149-
'New Reiter'
150-
)
151-
152-
def test_edit_transform(self):
153-
edited = ReplaceTransformer('Tab', 'Reiter').visit(self.resource)
154-
self.assertEqual(
155-
edited.body[4].attributes[0].value.elements[0].value,
156-
'New Reiter'
157-
)
158-
159-
def test_edit_cloned(self):
160-
edited = ReplaceTransformer('Tab', 'Reiter').visit(self.resource.clone())
161-
self.assertEqual(
162-
edited.body[4].attributes[0].value.elements[0].value,
163-
'New Reiter'
164-
)
165-
166-
167-
def gather_stats(method, repeat=10, number=50):
168-
t = timeit.Timer(
169-
setup='''
170-
from tests.syntax import test_visitor
171-
test = test_visitor.TestPerf('test_{}')
172-
test.setUp()
173-
'''.format(method),
174-
stmt='test.test_{}()'.format(method)
175-
)
176-
return [
177-
result/number for result in
178-
t.repeat(repeat=repeat, number=number)
179-
]
180-
181-
182-
if __name__ == '__main__':
183-
for m in (
184-
'traverse',
185-
'visitor',
186-
'edit_traverse',
187-
'edit_transform',
188-
'edit_cloned',
189-
):
190-
results = gather_stats(m)
191-
try:
192-
import statistics
193-
print("{}:\t{}".format(m, statistics.mean(results)))
194-
except ImportError:
195-
print("{}:\t{}".format(m, sum(results)/len(results)))

0 commit comments

Comments
 (0)