|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | | -from io import StringIO |
16 | | -import json |
17 | | -import os |
18 | | -import pathlib |
19 | | -import re |
20 | | -import sys |
| 15 | +import warnings |
21 | 16 |
|
22 | | -import em |
23 | | -from rosidl_parser.definition import IdlLocator |
24 | | -from rosidl_parser.parser import parse_idl_file |
| 17 | +from rosidl_pycommon import * # noqa: F401, F403 |
25 | 18 |
|
26 | | - |
27 | | -def convert_camel_case_to_lower_case_underscore(value): |
28 | | - # insert an underscore before any upper case letter |
29 | | - # which is followed by a lower case letter |
30 | | - value = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', value) |
31 | | - # insert an underscore before any upper case letter |
32 | | - # which is preseded by a lower case letter or number |
33 | | - value = re.sub('([a-z0-9])([A-Z])', r'\1_\2', value) |
34 | | - return value.lower() |
35 | | - |
36 | | - |
37 | | -def read_generator_arguments(input_file): |
38 | | - with open(input_file, mode='r', encoding='utf-8') as h: |
39 | | - return json.load(h) |
40 | | - |
41 | | - |
42 | | -def get_newest_modification_time(target_dependencies): |
43 | | - newest_timestamp = None |
44 | | - for dep in target_dependencies: |
45 | | - ts = os.path.getmtime(dep) |
46 | | - if newest_timestamp is None or ts > newest_timestamp: |
47 | | - newest_timestamp = ts |
48 | | - return newest_timestamp |
49 | | - |
50 | | - |
51 | | -def generate_files( |
52 | | - generator_arguments_file, mapping, additional_context=None, |
53 | | - keep_case=False, post_process_callback=None |
54 | | -): |
55 | | - args = read_generator_arguments(generator_arguments_file) |
56 | | - |
57 | | - template_basepath = pathlib.Path(args['template_dir']) |
58 | | - for template_filename in mapping.keys(): |
59 | | - assert (template_basepath / template_filename).exists(), \ |
60 | | - 'Could not find template: ' + template_filename |
61 | | - |
62 | | - latest_target_timestamp = get_newest_modification_time(args['target_dependencies']) |
63 | | - generated_files = [] |
64 | | - |
65 | | - for idl_tuple in args.get('idl_tuples', []): |
66 | | - idl_parts = idl_tuple.rsplit(':', 1) |
67 | | - assert len(idl_parts) == 2 |
68 | | - locator = IdlLocator(*idl_parts) |
69 | | - idl_rel_path = pathlib.Path(idl_parts[1]) |
70 | | - idl_stem = idl_rel_path.stem |
71 | | - if not keep_case: |
72 | | - idl_stem = convert_camel_case_to_lower_case_underscore(idl_stem) |
73 | | - try: |
74 | | - idl_file = parse_idl_file(locator) |
75 | | - for template_file, generated_filename in mapping.items(): |
76 | | - generated_file = os.path.join( |
77 | | - args['output_dir'], str(idl_rel_path.parent), |
78 | | - generated_filename % idl_stem) |
79 | | - generated_files.append(generated_file) |
80 | | - data = { |
81 | | - 'package_name': args['package_name'], |
82 | | - 'interface_path': idl_rel_path, |
83 | | - 'content': idl_file.content, |
84 | | - } |
85 | | - if additional_context is not None: |
86 | | - data.update(additional_context) |
87 | | - expand_template( |
88 | | - os.path.basename(template_file), data, |
89 | | - generated_file, minimum_timestamp=latest_target_timestamp, |
90 | | - template_basepath=template_basepath, |
91 | | - post_process_callback=post_process_callback) |
92 | | - except Exception as e: |
93 | | - print( |
94 | | - 'Error processing idl file: ' + |
95 | | - str(locator.get_absolute_path()), file=sys.stderr) |
96 | | - raise(e) |
97 | | - |
98 | | - return generated_files |
99 | | - |
100 | | - |
101 | | -template_prefix_path = [] |
102 | | - |
103 | | - |
104 | | -def get_template_path(template_name): |
105 | | - global template_prefix_path |
106 | | - for basepath in template_prefix_path: |
107 | | - template_path = basepath / template_name |
108 | | - if template_path.exists(): |
109 | | - return template_path |
110 | | - raise RuntimeError(f"Failed to find template '{template_name}'") |
111 | | - |
112 | | - |
113 | | -interpreter = None |
114 | | - |
115 | | - |
116 | | -def expand_template( |
117 | | - template_name, data, output_file, minimum_timestamp=None, |
118 | | - template_basepath=None, post_process_callback=None |
119 | | -): |
120 | | - # in the legacy API the first argument was the path to the template |
121 | | - if template_basepath is None: |
122 | | - template_name = pathlib.Path(template_name) |
123 | | - template_basepath = template_name.parent |
124 | | - template_name = template_name.name |
125 | | - |
126 | | - global interpreter |
127 | | - output = StringIO() |
128 | | - interpreter = em.Interpreter( |
129 | | - output=output, |
130 | | - options={ |
131 | | - em.BUFFERED_OPT: True, |
132 | | - em.RAW_OPT: True, |
133 | | - }, |
134 | | - ) |
135 | | - |
136 | | - global template_prefix_path |
137 | | - template_prefix_path.append(template_basepath) |
138 | | - template_path = get_template_path(template_name) |
139 | | - |
140 | | - # create copy before manipulating |
141 | | - data = dict(data) |
142 | | - _add_helper_functions(data) |
143 | | - |
144 | | - try: |
145 | | - with template_path.open('r') as h: |
146 | | - template_content = h.read() |
147 | | - interpreter.invoke( |
148 | | - 'beforeFile', name=template_name, file=h, locals=data) |
149 | | - interpreter.string(template_content, template_path, locals=data) |
150 | | - interpreter.invoke('afterFile') |
151 | | - except Exception as e: # noqa: F841 |
152 | | - if os.path.exists(output_file): |
153 | | - os.remove(output_file) |
154 | | - print(f"{e.__class__.__name__} when expanding '{template_name}' into " |
155 | | - f"'{output_file}': {e}", file=sys.stderr) |
156 | | - raise |
157 | | - finally: |
158 | | - template_prefix_path.pop() |
159 | | - |
160 | | - content = output.getvalue() |
161 | | - interpreter.shutdown() |
162 | | - |
163 | | - if post_process_callback: |
164 | | - content = post_process_callback(content) |
165 | | - |
166 | | - # only overwrite file if necessary |
167 | | - # which is either when the timestamp is too old or when the content is different |
168 | | - if os.path.exists(output_file): |
169 | | - timestamp = os.path.getmtime(output_file) |
170 | | - if minimum_timestamp is None or timestamp > minimum_timestamp: |
171 | | - with open(output_file, 'r', encoding='utf-8') as h: |
172 | | - if h.read() == content: |
173 | | - return |
174 | | - else: |
175 | | - # create folder if necessary |
176 | | - try: |
177 | | - os.makedirs(os.path.dirname(output_file)) |
178 | | - except FileExistsError: |
179 | | - pass |
180 | | - |
181 | | - with open(output_file, 'w', encoding='utf-8') as h: |
182 | | - h.write(content) |
183 | | - |
184 | | - |
185 | | -def _add_helper_functions(data): |
186 | | - data['TEMPLATE'] = _expand_template |
187 | | - |
188 | | - |
189 | | -def _expand_template(template_name, **kwargs): |
190 | | - global interpreter |
191 | | - template_path = get_template_path(template_name) |
192 | | - _add_helper_functions(kwargs) |
193 | | - with template_path.open('r') as h: |
194 | | - interpreter.invoke( |
195 | | - 'beforeInclude', name=str(template_path), file=h, locals=kwargs) |
196 | | - content = h.read() |
197 | | - try: |
198 | | - interpreter.string(content, str(template_path), kwargs) |
199 | | - except Exception as e: # noqa: F841 |
200 | | - print(f"{e.__class__.__name__} in template '{template_path}': {e}", |
201 | | - file=sys.stderr) |
202 | | - raise |
203 | | - interpreter.invoke('afterInclude') |
| 19 | +warnings.warn( |
| 20 | + "The 'rosidl_cmake' Python module is deprecated. Use 'rosidl_pycommon' instead.", |
| 21 | + UserWarning |
| 22 | +) |
0 commit comments