Skip to content

Commit 41bfdab

Browse files
committed
fix(generate_parameter_library_py): nested mappings double dot bug (#10)
* allows for nested mapping of parameters in python (removes the double dot bug)
1 parent 9084042 commit 41bfdab

File tree

3 files changed

+162
-4
lines changed

3 files changed

+162
-4
lines changed

generate_parameter_library_py/generate_parameter_library_py/jinja_templates/python/declare_runtime_parameter

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ for value_{{loop.index}} in updated_params.{{mapped_param}}:
77
{% if struct_name != "" %}
88
{{param_struct_instance}}.{{struct_name}}{% for map in parameter_map%}.add_entry(value_{{loop.index}}){% endfor %}
99
entry = {{param_struct_instance}}.{{struct_name}}{% for map in parameter_map%}.get_entry(value_{{loop.index}}){% endfor %}
10-
param_name = f"{self.prefix_}{{struct_name}}.{% for map in parameter_map%}{value_{{loop.index}}}.{% endfor %}{{parameter_field}}"
10+
param_name = f"{self.prefix_}{{struct_name}}.{% for map in parameter_map%}{value_{{loop.index}}}{% if not loop.last %}.{% endif %}{% endfor %}.{{parameter_field}}"
1111
{% else %}
1212
{{param_struct_instance}}{% for map in parameter_map%}.add_entry(value_{{loop.index}}){% endfor %}
1313
entry = {{param_struct_instance}}{% for map in parameter_map%}.get_entry(value_{{loop.index}}){% endfor %}
14-
param_name = f"{self.prefix_}{% for map in parameter_map%}{value_{{loop.index}}}.{% endfor %}{{parameter_field}}"
14+
param_name = f"{self.prefix_}{% for map in parameter_map%}{value_{{loop.index}}}{% if not loop.last %}.{% endif %}{% endfor %}.{{parameter_field}}"
1515
{% endif -%}
1616
if not self.node_.has_parameter(self.prefix_ + param_name):
1717
{%- filter indent(width=4) %}

generate_parameter_library_py/generate_parameter_library_py/jinja_templates/python/update_runtime_parameter

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ for value_{{loop.index}} in updated_params.{{mapped_param}}:
55
{% endfor -%}
66
{%- filter indent(width=4*(1+mapped_params|length)) %}
77
{% if struct_name != "" %}
8-
param_name = f"{self.prefix_}{{struct_name}}{% for map in parameter_map%}.{value_{{loop.index}}}.{% endfor %}{{parameter_field}}"
8+
param_name = f"{self.prefix_}{{struct_name}}{% for map in parameter_map%}.{value_{{loop.index}}}{% endfor %}.{{parameter_field}}"
99
{% else %}
10-
param_name = f"{self.prefix_}{% for map in parameter_map%}.{value_{{loop.index}}}.{% endfor %}{{parameter_field}}"
10+
param_name = f"{self.prefix_}{% for map in parameter_map%}{value_{{loop.index}}}{% if not loop.last %}.{% endif %}{% endfor %}.{{parameter_field}}"
1111
{% endif -%}
1212
if param.name == param_name:
1313
{%- filter indent(width=4) %}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
import tempfile
4+
import os
5+
6+
from generate_parameter_library_py.generate_python_module import run as run_python
7+
8+
9+
def test_nested_map_parameter_names():
10+
"""Test that nested map parameters don't generate double dots in parameter names."""
11+
12+
nested_map_yaml_content = """test_namespace:
13+
config_groups:
14+
__map_group_ids:
15+
max_value:
16+
type: double
17+
default_value: 100.0
18+
validation:
19+
bounds<>: [-100.0, 100.0]
20+
__map_item_ids:
21+
enabled:
22+
type: bool
23+
default_value: true
24+
min_param:
25+
type: double
26+
default_value: -1.0
27+
validation:
28+
bounds<>: [-1.0, 1.0]
29+
max_param:
30+
type: double
31+
default_value: 1.0
32+
validation:
33+
bounds<>: [-1.0, 1.0]
34+
control_id:
35+
type: string
36+
default_value: ""
37+
"""
38+
39+
with tempfile.NamedTemporaryFile(
40+
mode='w', suffix='.yaml', delete=False
41+
) as yaml_file:
42+
yaml_file.write(nested_map_yaml_content)
43+
yaml_file.flush()
44+
45+
with tempfile.NamedTemporaryFile(
46+
mode='w', suffix='.py', delete=False
47+
) as output_file:
48+
try:
49+
run_python(output_file.name, yaml_file.name, 'test_validate.hpp')
50+
51+
with open(output_file.name, 'r') as f:
52+
generated_code = f.read()
53+
54+
# Check that no parameter names have double dots
55+
lines = generated_code.split('\n')
56+
param_name_lines = [
57+
line
58+
for line in lines
59+
if 'param_name' in line and 'config_groups' in line
60+
]
61+
62+
# Assert there are parameter name lines (test that our test is working)
63+
assert (
64+
len(param_name_lines) > 0
65+
), 'Should have found parameter name lines'
66+
67+
# Check each param_name line for double dots
68+
for line in param_name_lines:
69+
assert (
70+
'..' not in line
71+
), f'Found double dots in parameter name: {line.strip()}'
72+
73+
expected_patterns = [
74+
'config_groups.{value_1}.max_value',
75+
'config_groups.{value_1}.{value_2}.enabled',
76+
'config_groups.{value_1}.{value_2}.min_param',
77+
'config_groups.{value_1}.{value_2}.max_param',
78+
'config_groups.{value_1}.{value_2}.control_id',
79+
]
80+
81+
for pattern in expected_patterns:
82+
pattern_found = any(pattern in line for line in param_name_lines)
83+
assert (
84+
pattern_found
85+
), f"Expected pattern '{pattern}' not found in generated code"
86+
87+
finally:
88+
# Clean up temporary files
89+
os.unlink(yaml_file.name)
90+
os.unlink(output_file.name)
91+
92+
93+
def test_single_map_parameter_names():
94+
"""Test that single map parameters still work correctly after the fix."""
95+
96+
single_map_yaml_content = """test_namespace:
97+
params:
98+
__map_keys:
99+
value_a:
100+
type: double
101+
default_value: 1.0
102+
validation:
103+
gt_eq<>: [ 0 ]
104+
value_b:
105+
type: double
106+
value_c:
107+
type: double
108+
default_value: 1.0
109+
"""
110+
111+
with tempfile.NamedTemporaryFile(
112+
mode='w', suffix='.yaml', delete=False
113+
) as yaml_file:
114+
yaml_file.write(single_map_yaml_content)
115+
yaml_file.flush()
116+
117+
with tempfile.NamedTemporaryFile(
118+
mode='w', suffix='.py', delete=False
119+
) as output_file:
120+
try:
121+
run_python(output_file.name, yaml_file.name, 'test_validate.hpp')
122+
123+
with open(output_file.name, 'r') as f:
124+
generated_code = f.read()
125+
126+
# Check that no parameter names have double dots
127+
lines = generated_code.split('\n')
128+
param_name_lines = [
129+
line for line in lines if 'param_name' in line and 'params' in line
130+
]
131+
132+
# Assert there are parameter name lines (test that our test is working)
133+
assert (
134+
len(param_name_lines) > 0
135+
), 'Should have found parameter name lines'
136+
137+
# Check each param_name line for double dots
138+
for line in param_name_lines:
139+
assert (
140+
'..' not in line
141+
), f'Found double dots in parameter name: {line.strip()}'
142+
143+
expected_patterns = [
144+
'params.{value_1}.value_a',
145+
'params.{value_1}.value_b',
146+
'params.{value_1}.value_c',
147+
]
148+
149+
for pattern in expected_patterns:
150+
pattern_found = any(pattern in line for line in param_name_lines)
151+
assert (
152+
pattern_found
153+
), f"Expected pattern '{pattern}' not found in generated code"
154+
155+
finally:
156+
# Clean up temporary files
157+
os.unlink(yaml_file.name)
158+
os.unlink(output_file.name)

0 commit comments

Comments
 (0)