Skip to content

Commit bee4522

Browse files
authored
Add a depth-max for test logs
Merge pull request #1150 from openfisca/depth-max
2 parents b9ead83 + 3795c3e commit bee4522

File tree

8 files changed

+105
-54
lines changed

8 files changed

+105
-54
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
### 35.9.0 [#1150](https://github.com/openfisca/openfisca-core/pull/1150)
4+
5+
#### New Features
6+
7+
- Introduce a maximal depth for compuation logs
8+
- Allows for limiting the depth of the computation log chain
9+
310
### 35.8.6 [#1145](https://github.com/openfisca/openfisca-core/pull/1145)
411

512
#### Technical changes

openfisca_core/scripts/openfisca_command.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ def build_test_parser(parser):
3838
parser.add_argument('-p', '--pdb', action = 'store_true', default = False, help = "drop into debugger on failures or errors")
3939
parser.add_argument('--performance-graph', '--performance', action = 'store_true', default = False, help = "output a performance graph in a 'performance_graph.html' file")
4040
parser.add_argument('--performance-tables', action = 'store_true', default = False, help = "output performance CSV tables")
41-
parser.add_argument('-v', '--verbose', action = 'store_true', default = False, help = "increase output verbosity")
41+
parser.add_argument('-v', '--verbose', action = 'store_true', default = False, help = "increase output verbosity. If specified, output the entire calculation trace.")
42+
parser.add_argument('-a', '--aggregate', action = 'store_true', default = False, help = "increase output verbosity to aggregate. If specified, output the avg, max, and min values of the calculation trace. This flag has no effect without --verbose.")
43+
parser.add_argument('-d', '--max-depth', type = int, default = None, help = "set maximal verbosity depth. If specified, output the calculation trace up to the provided depth. This flag has no effect without --verbose.")
4244
parser.add_argument('-o', '--only-variables', nargs = '*', default = None, help = "variables to test. If specified, only test the given variables.")
4345
parser.add_argument('-i', '--ignore-variables', nargs = '*', default = None, help = "variables to ignore. If specified, do not test the given variables.")
4446

openfisca_core/scripts/run_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ def main(parser):
1919
'performance_graph': args.performance_graph,
2020
'performance_tables': args.performance_tables,
2121
'verbose': args.verbose,
22+
'aggregate': args.aggregate,
23+
'max_depth': args.max_depth,
2224
'name_filter': args.name_filter,
2325
'only_variables': args.only_variables,
2426
'ignore_variables': args.ignore_variables,

openfisca_core/tools/test_runner.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ def runtest(self):
144144
period = self.test.get('period')
145145
max_spiral_loops = self.test.get('max_spiral_loops')
146146
verbose = self.options.get('verbose')
147+
aggregate = self.options.get('aggregate')
148+
max_depth = self.options.get('max_depth')
147149
performance_graph = self.options.get('performance_graph')
148150
performance_tables = self.options.get('performance_tables')
149151

@@ -165,15 +167,15 @@ def runtest(self):
165167
finally:
166168
tracer = self.simulation.tracer
167169
if verbose:
168-
self.print_computation_log(tracer)
170+
self.print_computation_log(tracer, aggregate, max_depth)
169171
if performance_graph:
170172
self.generate_performance_graph(tracer)
171173
if performance_tables:
172174
self.generate_performance_tables(tracer)
173175

174-
def print_computation_log(self, tracer):
176+
def print_computation_log(self, tracer, aggregate, max_depth):
175177
print("Computation log:") # noqa T001
176-
tracer.print_computation_log()
178+
tracer.print_computation_log(aggregate, max_depth)
177179

178180
def generate_performance_graph(self, tracer):
179181
tracer.generate_performance_graph('.')

openfisca_core/tracers/computation_log.py

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,74 +30,93 @@ def display(
3030

3131
return numpy.array2string(value, max_line_width = float("inf"))
3232

33-
def _get_node_log(
33+
def lines(
3434
self,
35-
node: tracers.TraceNode,
36-
depth: int,
37-
aggregate: bool,
35+
aggregate: bool = False,
36+
max_depth: Optional[int] = None,
3837
) -> List[str]:
38+
depth = 1
39+
40+
lines_by_tree = [
41+
self._get_node_log(node, depth, aggregate, max_depth)
42+
for node
43+
in self._full_tracer.trees
44+
]
3945

40-
def print_line(depth: int, node: tracers.TraceNode) -> str:
41-
indent = ' ' * depth
42-
value = node.value
46+
return self._flatten(lines_by_tree)
4347

44-
if value is None:
45-
formatted_value = "{'avg': '?', 'max': '?', 'min': '?'}"
48+
def print_log(self, aggregate = False, max_depth = None) -> None:
49+
"""
50+
Print the computation log of a simulation.
4651
47-
elif aggregate:
48-
try:
49-
formatted_value = str({
50-
'avg': numpy.mean(value),
51-
'max': numpy.max(value),
52-
'min': numpy.min(value),
53-
})
52+
If ``aggregate`` is ``False`` (default), print the value of each
53+
computed vector.
54+
55+
If ``aggregate`` is ``True``, only print the minimum, maximum, and
56+
average value of each computed vector.
57+
58+
This mode is more suited for simulations on a large population.
5459
55-
except TypeError:
56-
formatted_value = "{'avg': '?', 'max': '?', 'min': '?'}"
60+
If ``max_depth`` is ``None`` (default), print the entire computation.
5761
58-
else:
59-
formatted_value = self.display(value)
62+
If ``max_depth`` is set, for example to ``3``, only print computed
63+
vectors up to a depth of ``max_depth``.
64+
"""
65+
for line in self.lines(aggregate, max_depth):
66+
print(line) # noqa T001
67+
68+
def _get_node_log(
69+
self,
70+
node: tracers.TraceNode,
71+
depth: int,
72+
aggregate: bool,
73+
max_depth: Optional[int],
74+
) -> List[str]:
6075

61-
return f"{indent}{node.name}<{node.period}> >> {formatted_value}"
76+
if max_depth is not None and depth > max_depth:
77+
return []
6278

63-
node_log = [print_line(depth, node)]
79+
node_log = [self._print_line(depth, node, aggregate, max_depth)]
6480

6581
children_logs = [
66-
self._get_node_log(child, depth + 1, aggregate)
82+
self._get_node_log(child, depth + 1, aggregate, max_depth)
6783
for child
6884
in node.children
6985
]
7086

7187
return node_log + self._flatten(children_logs)
7288

73-
def _flatten(
89+
def _print_line(
7490
self,
75-
list_of_lists: List[List[str]],
76-
) -> List[str]:
77-
return [item for _list in list_of_lists for item in _list]
78-
79-
def lines(self, aggregate: bool = False) -> List[str]:
80-
depth = 1
91+
depth: int,
92+
node: tracers.TraceNode,
93+
aggregate: bool,
94+
max_depth: Optional[int],
95+
) -> str:
96+
indent = ' ' * depth
97+
value = node.value
8198

82-
lines_by_tree = [
83-
self._get_node_log(node, depth, aggregate)
84-
for node
85-
in self._full_tracer.trees
86-
]
99+
if value is None:
100+
formatted_value = "{'avg': '?', 'max': '?', 'min': '?'}"
87101

88-
return self._flatten(lines_by_tree)
102+
elif aggregate:
103+
try:
104+
formatted_value = str({
105+
'avg': numpy.mean(value),
106+
'max': numpy.max(value),
107+
'min': numpy.min(value),
108+
})
89109

90-
def print_log(self, aggregate = False) -> None:
91-
"""
92-
Print the computation log of a simulation.
110+
except TypeError:
111+
formatted_value = "{'avg': '?', 'max': '?', 'min': '?'}"
93112

94-
If ``aggregate`` is ``False`` (default), print the value of each
95-
computed vector.
113+
else:
114+
formatted_value = self.display(value)
96115

97-
If ``aggregate`` is ``True``, only print the minimum, maximum, and
98-
average value of each computed vector.
116+
return f"{indent}{node.name}<{node.period}> >> {formatted_value}"
99117

100-
This mode is more suited for simulations on a large population.
101-
"""
102-
for line in self.lines(aggregate):
103-
print(line) # noqa T001
118+
def _flatten(
119+
self,
120+
lists: List[List[str]],
121+
) -> List[str]:
122+
return [item for list_ in lists for item in list_]

openfisca_core/tracers/full_tracer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ def flat_trace(self) -> tracers.FlatTrace:
121121
def _get_time_in_sec(self) -> float:
122122
return time.time_ns() / (10**9)
123123

124-
def print_computation_log(self, aggregate = False):
125-
self.computation_log.print_log(aggregate)
124+
def print_computation_log(self, aggregate = False, max_depth = None):
125+
self.computation_log.print_log(aggregate, max_depth)
126126

127127
def generate_performance_graph(self, dir_path: str) -> None:
128128
self.performance_log.generate_graph(dir_path)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
setup(
5050
name = 'OpenFisca-Core',
51-
version = '35.8.6',
51+
version = '35.9.0',
5252
author = 'OpenFisca Team',
5353
author_email = 'contact@openfisca.org',
5454
classifiers = [

tests/core/test_tracers.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,25 @@ def test_log_aggregate_with_strings(tracer):
421421
assert lines[0] == " A<2017> >> {'avg': '?', 'max': '?', 'min': '?'}"
422422

423423

424+
def test_log_max_depth(tracer):
425+
tracer._enter_calculation("A", 2017)
426+
tracer._enter_calculation("B", 2017)
427+
tracer._enter_calculation("C", 2017)
428+
tracer.record_calculation_result(np.asarray([3]))
429+
tracer._exit_calculation()
430+
tracer.record_calculation_result(np.asarray([2]))
431+
tracer._exit_calculation()
432+
tracer.record_calculation_result(np.asarray([1]))
433+
tracer._exit_calculation()
434+
435+
assert len(tracer.computation_log.lines()) == 3
436+
assert len(tracer.computation_log.lines(max_depth = 4)) == 3
437+
assert len(tracer.computation_log.lines(max_depth = 3)) == 3
438+
assert len(tracer.computation_log.lines(max_depth = 2)) == 2
439+
assert len(tracer.computation_log.lines(max_depth = 1)) == 1
440+
assert len(tracer.computation_log.lines(max_depth = 0)) == 0
441+
442+
424443
def test_no_wrapping(tracer):
425444
tracer._enter_calculation("A", 2017)
426445
tracer.record_calculation_result(HousingOccupancyStatus.encode(np.repeat('tenant', 100)))

0 commit comments

Comments
 (0)