artefacts-cli 0.7.3__py3-none-any.whl → 0.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- artefacts/cli/__init__.py +66 -18
- artefacts/cli/app.py +209 -166
- artefacts/cli/app_containers.py +116 -24
- artefacts/cli/app_containers.pyi +3 -0
- artefacts/cli/bagparser.py +4 -0
- artefacts/cli/config.py +62 -0
- artefacts/cli/constants.py +7 -0
- artefacts/cli/containers/__init__.py +5 -5
- artefacts/cli/containers/docker_cm.py +175 -0
- artefacts/cli/containers/docker_utils.py +98 -0
- artefacts/cli/containers/utils.py +20 -8
- artefacts/cli/helpers.py +55 -0
- artefacts/cli/i18n.py +30 -0
- artefacts/cli/locales/art.pot +524 -0
- artefacts/cli/locales/base.pot +936 -0
- artefacts/cli/locales/click.pot +438 -0
- artefacts/cli/locales/ja_JP/LC_MESSAGES/artefacts.mo +0 -0
- artefacts/cli/logger.py +21 -5
- artefacts/cli/other.py +4 -0
- artefacts/cli/ros1.py +21 -6
- artefacts/cli/ros2.py +31 -15
- artefacts/cli/utils.py +8 -4
- artefacts/cli/utils_ros.py +8 -4
- artefacts/cli/version.py +2 -2
- artefacts/copava/__init__.py +1 -0
- {artefacts_cli-0.7.3.dist-info → artefacts_cli-0.9.1.dist-info}/METADATA +10 -3
- artefacts_cli-0.9.1.dist-info/RECORD +34 -0
- {artefacts_cli-0.7.3.dist-info → artefacts_cli-0.9.1.dist-info}/WHEEL +1 -1
- artefacts/cli/containers/docker.py +0 -119
- artefacts_cli-0.7.3.dist-info/RECORD +0 -24
- {artefacts_cli-0.7.3.dist-info → artefacts_cli-0.9.1.dist-info}/entry_points.txt +0 -0
- {artefacts_cli-0.7.3.dist-info → artefacts_cli-0.9.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,438 @@
|
|
1
|
+
# Translations template for artefacts.
|
2
|
+
# Copyright (C) 2025 Asteria ART
|
3
|
+
# This file is distributed under the same license as the artefacts project.
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
|
5
|
+
#
|
6
|
+
#, fuzzy
|
7
|
+
msgid ""
|
8
|
+
msgstr ""
|
9
|
+
"Project-Id-Version: artefacts 0.8.5.dev2\n"
|
10
|
+
"Report-Msgid-Bugs-To: dev@artefacts.com\n"
|
11
|
+
"POT-Creation-Date: 2025-04-30 18:06+0900\n"
|
12
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15
|
+
"MIME-Version: 1.0\n"
|
16
|
+
"Content-Type: text/plain; charset=utf-8\n"
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
18
|
+
"Generated-By: Babel 2.17.0\n"
|
19
|
+
|
20
|
+
#: venv/lib/python3.10/site-packages/click/_termui_impl.py:179
|
21
|
+
msgid "d"
|
22
|
+
msgstr ""
|
23
|
+
|
24
|
+
#: venv/lib/python3.10/site-packages/click/_termui_impl.py:606
|
25
|
+
#, python-brace-format
|
26
|
+
msgid "{editor}: Editing failed"
|
27
|
+
msgstr ""
|
28
|
+
|
29
|
+
#: venv/lib/python3.10/site-packages/click/_termui_impl.py:610
|
30
|
+
#, python-brace-format
|
31
|
+
msgid "{editor}: Editing failed: {e}"
|
32
|
+
msgstr ""
|
33
|
+
|
34
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1002
|
35
|
+
#, python-brace-format
|
36
|
+
msgid ""
|
37
|
+
"The parameter {param} is used more than once. Remove its duplicate as "
|
38
|
+
"parameters should be unique."
|
39
|
+
msgstr ""
|
40
|
+
|
41
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1094
|
42
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1131
|
43
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2597
|
44
|
+
#, python-brace-format
|
45
|
+
msgid "(DEPRECATED: {target})"
|
46
|
+
msgstr ""
|
47
|
+
|
48
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1096
|
49
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1133
|
50
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2599
|
51
|
+
msgid "(DEPRECATED)"
|
52
|
+
msgstr ""
|
53
|
+
|
54
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1098
|
55
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1135
|
56
|
+
#, python-brace-format
|
57
|
+
msgid "{text} {deprecated_message}"
|
58
|
+
msgstr ""
|
59
|
+
|
60
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1154
|
61
|
+
msgid "Options"
|
62
|
+
msgstr ""
|
63
|
+
|
64
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1216
|
65
|
+
#, python-brace-format
|
66
|
+
msgid "Got unexpected extra argument ({args})"
|
67
|
+
msgid_plural "Got unexpected extra arguments ({args})"
|
68
|
+
msgstr[0] ""
|
69
|
+
msgstr[1] ""
|
70
|
+
|
71
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1235
|
72
|
+
#, python-brace-format
|
73
|
+
msgid "DeprecationWarning: The command {name!r} is deprecated.{extra_message}"
|
74
|
+
msgstr ""
|
75
|
+
|
76
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1419
|
77
|
+
msgid "Aborted!"
|
78
|
+
msgstr ""
|
79
|
+
|
80
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1793
|
81
|
+
msgid "Commands"
|
82
|
+
msgstr ""
|
83
|
+
|
84
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1824
|
85
|
+
msgid "Missing command."
|
86
|
+
msgstr ""
|
87
|
+
|
88
|
+
#: venv/lib/python3.10/site-packages/click/core.py:1902
|
89
|
+
#, python-brace-format
|
90
|
+
msgid "No such command {name!r}."
|
91
|
+
msgstr ""
|
92
|
+
|
93
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2177
|
94
|
+
#, python-brace-format
|
95
|
+
msgid "'default' {subject} must match nargs={nargs}."
|
96
|
+
msgstr ""
|
97
|
+
|
98
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2185
|
99
|
+
#, python-brace-format
|
100
|
+
msgid ""
|
101
|
+
"The {type_name} '{readable_name}' is deprecated and still required. A "
|
102
|
+
"deprecated {type_name} cannot be required."
|
103
|
+
msgstr ""
|
104
|
+
|
105
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2326
|
106
|
+
msgid "Value must be an iterable."
|
107
|
+
msgstr ""
|
108
|
+
|
109
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2347
|
110
|
+
#, python-brace-format
|
111
|
+
msgid "Takes {nargs} values but 1 was given."
|
112
|
+
msgid_plural "Takes {nargs} values but {len} were given."
|
113
|
+
msgstr[0] ""
|
114
|
+
msgstr[1] ""
|
115
|
+
|
116
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2427
|
117
|
+
#, python-brace-format
|
118
|
+
msgid ""
|
119
|
+
"DeprecationWarning: The {param_type} {name!r} is "
|
120
|
+
"deprecated.{extra_message}"
|
121
|
+
msgstr ""
|
122
|
+
|
123
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2702
|
124
|
+
#, python-brace-format
|
125
|
+
msgid " (env var: '{var}')"
|
126
|
+
msgstr ""
|
127
|
+
|
128
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2716
|
129
|
+
#, python-brace-format
|
130
|
+
msgid "Name '{name}' defined twice"
|
131
|
+
msgstr ""
|
132
|
+
|
133
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2732
|
134
|
+
#, python-brace-format
|
135
|
+
msgid "Boolean option {decl!r} cannot use the same flag for true/false."
|
136
|
+
msgstr ""
|
137
|
+
|
138
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2751
|
139
|
+
#, python-brace-format
|
140
|
+
msgid "Could not determine name for option with declarations {decls!r}"
|
141
|
+
msgstr ""
|
142
|
+
|
143
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2758
|
144
|
+
#, python-brace-format
|
145
|
+
msgid ""
|
146
|
+
"No options defined but a name was passed ({name}). Did you mean to "
|
147
|
+
"declare an argument instead? Did you mean to pass '--{name}'?"
|
148
|
+
msgstr ""
|
149
|
+
|
150
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2835
|
151
|
+
#, python-brace-format
|
152
|
+
msgid "env var: {var}"
|
153
|
+
msgstr ""
|
154
|
+
|
155
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2838
|
156
|
+
#, python-brace-format
|
157
|
+
msgid "default: {default}"
|
158
|
+
msgstr ""
|
159
|
+
|
160
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2842
|
161
|
+
msgid "required"
|
162
|
+
msgstr ""
|
163
|
+
|
164
|
+
#: venv/lib/python3.10/site-packages/click/core.py:2898
|
165
|
+
msgid "(dynamic)"
|
166
|
+
msgstr ""
|
167
|
+
|
168
|
+
#: venv/lib/python3.10/site-packages/click/core.py:3128
|
169
|
+
#, python-brace-format
|
170
|
+
msgid "Arguments take exactly one parameter declaration, got {length}: {decls}."
|
171
|
+
msgstr ""
|
172
|
+
|
173
|
+
#: venv/lib/python3.10/site-packages/click/decorators.py:475
|
174
|
+
#, python-format
|
175
|
+
msgid "%(prog)s, version %(version)s"
|
176
|
+
msgstr ""
|
177
|
+
|
178
|
+
#: venv/lib/python3.10/site-packages/click/decorators.py:534
|
179
|
+
msgid "Show the version and exit."
|
180
|
+
msgstr ""
|
181
|
+
|
182
|
+
#: venv/lib/python3.10/site-packages/click/decorators.py:560
|
183
|
+
msgid "Show this message and exit."
|
184
|
+
msgstr ""
|
185
|
+
|
186
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:50
|
187
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:89
|
188
|
+
#, python-brace-format
|
189
|
+
msgid "Error: {message}"
|
190
|
+
msgstr ""
|
191
|
+
|
192
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:81
|
193
|
+
#, python-brace-format
|
194
|
+
msgid "Try '{command} {option}' for help."
|
195
|
+
msgstr ""
|
196
|
+
|
197
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:130
|
198
|
+
#, python-brace-format
|
199
|
+
msgid "Invalid value: {message}"
|
200
|
+
msgstr ""
|
201
|
+
|
202
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:132
|
203
|
+
#, python-brace-format
|
204
|
+
msgid "Invalid value for {param_hint}: {message}"
|
205
|
+
msgstr ""
|
206
|
+
|
207
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:190
|
208
|
+
msgid "Missing argument"
|
209
|
+
msgstr ""
|
210
|
+
|
211
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:192
|
212
|
+
msgid "Missing option"
|
213
|
+
msgstr ""
|
214
|
+
|
215
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:194
|
216
|
+
msgid "Missing parameter"
|
217
|
+
msgstr ""
|
218
|
+
|
219
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:196
|
220
|
+
#, python-brace-format
|
221
|
+
msgid "Missing {param_type}"
|
222
|
+
msgstr ""
|
223
|
+
|
224
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:203
|
225
|
+
#, python-brace-format
|
226
|
+
msgid "Missing parameter: {param_name}"
|
227
|
+
msgstr ""
|
228
|
+
|
229
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:223
|
230
|
+
#, python-brace-format
|
231
|
+
msgid "No such option: {name}"
|
232
|
+
msgstr ""
|
233
|
+
|
234
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:235
|
235
|
+
#, python-brace-format
|
236
|
+
msgid "Did you mean {possibility}?"
|
237
|
+
msgid_plural "(Possible options: {possibilities})"
|
238
|
+
msgstr[0] ""
|
239
|
+
msgstr[1] ""
|
240
|
+
|
241
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:282
|
242
|
+
msgid "unknown error"
|
243
|
+
msgstr ""
|
244
|
+
|
245
|
+
#: venv/lib/python3.10/site-packages/click/exceptions.py:289
|
246
|
+
#, python-brace-format
|
247
|
+
msgid "Could not open file {filename!r}: {message}"
|
248
|
+
msgstr ""
|
249
|
+
|
250
|
+
#: venv/lib/python3.10/site-packages/click/formatting.py:156
|
251
|
+
msgid "Usage:"
|
252
|
+
msgstr ""
|
253
|
+
|
254
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:154
|
255
|
+
#, python-brace-format
|
256
|
+
msgid "Invalid start character for option ({option})"
|
257
|
+
msgstr ""
|
258
|
+
|
259
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:190
|
260
|
+
#, python-brace-format
|
261
|
+
msgid "unknown action '{action}'"
|
262
|
+
msgstr ""
|
263
|
+
|
264
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:212
|
265
|
+
#, python-brace-format
|
266
|
+
msgid "Argument {name!r} takes {nargs} values."
|
267
|
+
msgstr ""
|
268
|
+
|
269
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:395
|
270
|
+
#, python-brace-format
|
271
|
+
msgid "Option {name!r} does not take a value."
|
272
|
+
msgstr ""
|
273
|
+
|
274
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:456
|
275
|
+
#, python-brace-format
|
276
|
+
msgid "Option {name!r} requires an argument."
|
277
|
+
msgid_plural "Option {name!r} requires {nargs} arguments."
|
278
|
+
msgstr[0] ""
|
279
|
+
msgstr[1] ""
|
280
|
+
|
281
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:527
|
282
|
+
#, python-brace-format
|
283
|
+
msgid ""
|
284
|
+
"'parser.{name}' is deprecated and will be removed in Click 9.0. The old "
|
285
|
+
"parser is available in 'optparse'."
|
286
|
+
msgstr ""
|
287
|
+
|
288
|
+
#: venv/lib/python3.10/site-packages/click/parser.py:540
|
289
|
+
msgid ""
|
290
|
+
"Importing 'parser.split_arg_string' is deprecated, it will only be "
|
291
|
+
"available in 'shell_completion' in Click 9.0."
|
292
|
+
msgstr ""
|
293
|
+
|
294
|
+
#: venv/lib/python3.10/site-packages/click/shell_completion.py:334
|
295
|
+
msgid "Shell completion is not supported for Bash versions older than 4.4."
|
296
|
+
msgstr ""
|
297
|
+
|
298
|
+
#: venv/lib/python3.10/site-packages/click/shell_completion.py:341
|
299
|
+
msgid "Couldn't detect Bash version, shell completion is not supported."
|
300
|
+
msgstr ""
|
301
|
+
|
302
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:162
|
303
|
+
msgid "Repeat for confirmation"
|
304
|
+
msgstr ""
|
305
|
+
|
306
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:178
|
307
|
+
msgid "Error: The value you entered was invalid."
|
308
|
+
msgstr ""
|
309
|
+
|
310
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:180
|
311
|
+
#, python-brace-format
|
312
|
+
msgid "Error: {e.message}"
|
313
|
+
msgstr ""
|
314
|
+
|
315
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:191
|
316
|
+
msgid "Error: The two entered values do not match."
|
317
|
+
msgstr ""
|
318
|
+
|
319
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:247
|
320
|
+
msgid "Error: invalid input"
|
321
|
+
msgstr ""
|
322
|
+
|
323
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:611
|
324
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:617
|
325
|
+
#, python-brace-format
|
326
|
+
msgid "Unknown color {colour!r}"
|
327
|
+
msgstr ""
|
328
|
+
|
329
|
+
#: venv/lib/python3.10/site-packages/click/termui.py:866
|
330
|
+
msgid "Press any key to continue..."
|
331
|
+
msgstr ""
|
332
|
+
|
333
|
+
#: venv/lib/python3.10/site-packages/click/types.py:340
|
334
|
+
#, python-brace-format
|
335
|
+
msgid ""
|
336
|
+
"Choose from:\n"
|
337
|
+
"\t{choices}"
|
338
|
+
msgstr ""
|
339
|
+
|
340
|
+
#: venv/lib/python3.10/site-packages/click/types.py:377
|
341
|
+
#, python-brace-format
|
342
|
+
msgid "{value!r} is not {choice}."
|
343
|
+
msgid_plural "{value!r} is not one of {choices}."
|
344
|
+
msgstr[0] ""
|
345
|
+
msgstr[1] ""
|
346
|
+
|
347
|
+
#: venv/lib/python3.10/site-packages/click/types.py:383
|
348
|
+
#, python-brace-format
|
349
|
+
msgid "Choice({choices})"
|
350
|
+
msgstr ""
|
351
|
+
|
352
|
+
#: venv/lib/python3.10/site-packages/click/types.py:468
|
353
|
+
#, python-brace-format
|
354
|
+
msgid "{value!r} does not match the format {format}."
|
355
|
+
msgid_plural "{value!r} does not match the formats {formats}."
|
356
|
+
msgstr[0] ""
|
357
|
+
msgstr[1] ""
|
358
|
+
|
359
|
+
#: venv/lib/python3.10/site-packages/click/types.py:490
|
360
|
+
#, python-brace-format
|
361
|
+
msgid "{value!r} is not a valid {number_type}."
|
362
|
+
msgstr ""
|
363
|
+
|
364
|
+
#: venv/lib/python3.10/site-packages/click/types.py:546
|
365
|
+
#, python-brace-format
|
366
|
+
msgid "{value} is not in the range {range}."
|
367
|
+
msgstr ""
|
368
|
+
|
369
|
+
#: venv/lib/python3.10/site-packages/click/types.py:687
|
370
|
+
#, python-brace-format
|
371
|
+
msgid "{value!r} is not a valid boolean."
|
372
|
+
msgstr ""
|
373
|
+
|
374
|
+
#: venv/lib/python3.10/site-packages/click/types.py:711
|
375
|
+
#, python-brace-format
|
376
|
+
msgid "{value!r} is not a valid UUID."
|
377
|
+
msgstr ""
|
378
|
+
|
379
|
+
#: venv/lib/python3.10/site-packages/click/types.py:905
|
380
|
+
msgid "file"
|
381
|
+
msgstr ""
|
382
|
+
|
383
|
+
#: venv/lib/python3.10/site-packages/click/types.py:907
|
384
|
+
msgid "directory"
|
385
|
+
msgstr ""
|
386
|
+
|
387
|
+
#: venv/lib/python3.10/site-packages/click/types.py:909
|
388
|
+
msgid "path"
|
389
|
+
msgstr ""
|
390
|
+
|
391
|
+
#: venv/lib/python3.10/site-packages/click/types.py:956
|
392
|
+
#, python-brace-format
|
393
|
+
msgid "{name} {filename!r} does not exist."
|
394
|
+
msgstr ""
|
395
|
+
|
396
|
+
#: venv/lib/python3.10/site-packages/click/types.py:965
|
397
|
+
#, python-brace-format
|
398
|
+
msgid "{name} {filename!r} is a file."
|
399
|
+
msgstr ""
|
400
|
+
|
401
|
+
#: venv/lib/python3.10/site-packages/click/types.py:973
|
402
|
+
#, python-brace-format
|
403
|
+
msgid "{name} {filename!r} is a directory."
|
404
|
+
msgstr ""
|
405
|
+
|
406
|
+
#: venv/lib/python3.10/site-packages/click/types.py:982
|
407
|
+
#, python-brace-format
|
408
|
+
msgid "{name} {filename!r} is not readable."
|
409
|
+
msgstr ""
|
410
|
+
|
411
|
+
#: venv/lib/python3.10/site-packages/click/types.py:991
|
412
|
+
#, python-brace-format
|
413
|
+
msgid "{name} {filename!r} is not writable."
|
414
|
+
msgstr ""
|
415
|
+
|
416
|
+
#: venv/lib/python3.10/site-packages/click/types.py:1000
|
417
|
+
#, python-brace-format
|
418
|
+
msgid "{name} {filename!r} is not executable."
|
419
|
+
msgstr ""
|
420
|
+
|
421
|
+
#: venv/lib/python3.10/site-packages/click/types.py:1067
|
422
|
+
#, python-brace-format
|
423
|
+
msgid "{len_type} values are required, but {len_value} was given."
|
424
|
+
msgid_plural "{len_type} values are required, but {len_value} were given."
|
425
|
+
msgstr[0] ""
|
426
|
+
msgstr[1] ""
|
427
|
+
|
428
|
+
#: venv/lib/python3.10/site-packages/click/types.py:1130
|
429
|
+
#, python-brace-format
|
430
|
+
msgid "Attempted to use an uninstantiated parameter type ({type})."
|
431
|
+
msgstr ""
|
432
|
+
|
433
|
+
#: venv/lib/python3.10/site-packages/click/utils.py:342
|
434
|
+
#: venv/lib/python3.10/site-packages/click/utils.py:363
|
435
|
+
#, python-brace-format
|
436
|
+
msgid "Unknown standard stream '{name}'"
|
437
|
+
msgstr ""
|
438
|
+
|
Binary file
|
artefacts/cli/logger.py
CHANGED
@@ -1,10 +1,26 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
3
|
|
4
|
-
logger = logging.getLogger()
|
4
|
+
logger = logging.getLogger("artefacts")
|
5
|
+
logger.setLevel(logging.INFO) # Allow INFO and above
|
5
6
|
|
6
|
-
default_handler = logging.StreamHandler(stream=sys.stderr)
|
7
|
-
default_handler.setLevel(logging.ERROR)
|
8
|
-
default_handler.setFormatter(logging.Formatter())
|
9
7
|
|
10
|
-
|
8
|
+
# INFO and WARNING messages go to stdout
|
9
|
+
class InfoWarningFilter(logging.Filter):
|
10
|
+
def filter(self, record):
|
11
|
+
return record.levelno in [logging.INFO, logging.WARNING]
|
12
|
+
|
13
|
+
|
14
|
+
info_handler = logging.StreamHandler(stream=sys.stdout)
|
15
|
+
info_handler.setLevel(logging.INFO)
|
16
|
+
info_handler.addFilter(InfoWarningFilter())
|
17
|
+
info_handler.setFormatter(logging.Formatter("%(message)s"))
|
18
|
+
|
19
|
+
# ERROR and above go to stderr
|
20
|
+
error_handler = logging.StreamHandler(stream=sys.stderr)
|
21
|
+
error_handler.setLevel(logging.ERROR)
|
22
|
+
error_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
|
23
|
+
|
24
|
+
logger.addHandler(info_handler)
|
25
|
+
logger.addHandler(error_handler)
|
26
|
+
logger.propagate = False
|
artefacts/cli/other.py
CHANGED
@@ -16,10 +16,14 @@ def generate_parameter_output(params: dict):
|
|
16
16
|
|
17
17
|
|
18
18
|
def run_other_tests(run):
|
19
|
+
"""Note: parameter names will be set as environment variables
|
20
|
+
(must be letters, numbers and underscores), and saved into yaml and json files
|
21
|
+
"""
|
19
22
|
scenario = run.params
|
20
23
|
if "params" in scenario:
|
21
24
|
generate_parameter_output(scenario["params"])
|
22
25
|
full_env = {**os.environ, **scenario.get("params", {})}
|
26
|
+
full_env["ARTEFACTS_SCENARIO_PARAMS_FILE"] = TMP_SCENARIO_PARAMS_YAML
|
23
27
|
|
24
28
|
command = scenario["run"]
|
25
29
|
run_and_save_logs(
|
artefacts/cli/ros1.py
CHANGED
@@ -4,6 +4,7 @@ from glob import glob
|
|
4
4
|
import os
|
5
5
|
import logging
|
6
6
|
|
7
|
+
from .i18n import localise
|
7
8
|
from .utils import run_and_save_logs
|
8
9
|
from .utils_ros import parse_tests_results
|
9
10
|
from .parameters import TMP_RUNTIME_PARAMS_YAML, TMP_SCENARIO_PARAMS_YAML
|
@@ -50,7 +51,9 @@ def generate_rosbag_args(scenario: dict) -> str:
|
|
50
51
|
return topics
|
51
52
|
else:
|
52
53
|
logging.warning(
|
53
|
-
|
54
|
+
localise(
|
55
|
+
"[warning in generate_rosbag_args] rosbag_record asks for 'subscriptions' but they are not specified. Falling back to default: no rosbag will be recorded"
|
56
|
+
)
|
54
57
|
)
|
55
58
|
return "none"
|
56
59
|
else:
|
@@ -101,10 +104,20 @@ def get_result_path(scenario, PKGDIR, PACKAGE):
|
|
101
104
|
)
|
102
105
|
return test_result_file_path
|
103
106
|
except Exception as e:
|
104
|
-
logging.error(f"[Exception in get_result_path()] {e}")
|
105
107
|
logging.error(
|
106
|
-
|
107
|
-
|
108
|
+
localise("[Exception in get_result_path()] {message}".format(message=e))
|
109
|
+
)
|
110
|
+
logging.error(
|
111
|
+
localise(
|
112
|
+
"Unable to parse the ros1 .launch specified ({testfile}) and the <test> tag within to find the unittest test method's name.".format(
|
113
|
+
testfile=scenario["ros_testfile"]
|
114
|
+
)
|
115
|
+
)
|
116
|
+
)
|
117
|
+
logging.error(
|
118
|
+
localise(
|
119
|
+
"Please ensure all ROS and unittest naming conventions are respected. Exiting.."
|
120
|
+
)
|
108
121
|
)
|
109
122
|
return None
|
110
123
|
|
@@ -210,12 +223,14 @@ def run_ros1_tests(run):
|
|
210
223
|
new_rosbags = set(rosbags).difference(set(preexisting_rosbags))
|
211
224
|
if len(new_rosbags) > 0:
|
212
225
|
new_rosbag = new_rosbags.pop()
|
213
|
-
logging.info(
|
226
|
+
logging.info(
|
227
|
+
localise("New rosbag found: {file_name}".format(file_name=new_rosbag))
|
228
|
+
)
|
214
229
|
# upload rosbag to dashboard
|
215
230
|
run.log_single_artifact(new_rosbag, "rosbag")
|
216
231
|
# perform any post processing, using the rosbag
|
217
232
|
if "rosbag_postprocess" in scenario.keys():
|
218
|
-
logging.info("starting rosbag postprocess")
|
233
|
+
logging.info(localise("starting rosbag postprocess"))
|
219
234
|
post_process_folder = os.path.expanduser(f"{PKGDIR}/{PACKAGE}_postprocess")
|
220
235
|
os.makedirs(post_process_folder, exist_ok=True)
|
221
236
|
existing_files = glob(f"{post_process_folder}/*")
|
artefacts/cli/ros2.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
import yaml
|
2
1
|
from glob import glob
|
3
2
|
import os
|
4
3
|
import shutil
|
5
4
|
|
5
|
+
import yaml
|
6
|
+
|
7
|
+
from .i18n import localise
|
6
8
|
from .utils import run_and_save_logs
|
7
9
|
from .utils_ros import parse_tests_results, get_TestSuite_error_result
|
8
10
|
from .parameters import TMP_SCENARIO_PARAMS_YAML
|
@@ -66,7 +68,11 @@ def generate_scenario_parameter_output(params: dict, param_file: str):
|
|
66
68
|
try:
|
67
69
|
node, pname = k.split("/")
|
68
70
|
except Exception:
|
69
|
-
print(
|
71
|
+
print(
|
72
|
+
localise(
|
73
|
+
"Problem with parameter name. Please ensure params are in the format `node/param`"
|
74
|
+
)
|
75
|
+
)
|
70
76
|
return
|
71
77
|
if node not in content:
|
72
78
|
content[node] = {"ros__parameters": {}}
|
@@ -93,8 +99,11 @@ def run_ros2_tests(run):
|
|
93
99
|
generate_scenario_parameter_output(
|
94
100
|
run.params["params"], TMP_SCENARIO_PARAMS_YAML
|
95
101
|
)
|
96
|
-
|
97
|
-
|
102
|
+
# We look for the directory as drilling down will find both
|
103
|
+
# the directory as well as the rosbag itself.
|
104
|
+
preexisting_rosbags = [
|
105
|
+
path for path in glob("**/rosbag2*", recursive=True) if os.path.isdir(path)
|
106
|
+
]
|
98
107
|
test_result_file_path = f"{run.output_path}/tests_junit.xml"
|
99
108
|
launch_arguments = [
|
100
109
|
f"{k}:={v}" for k, v in run.params.get("launch_arguments", {}).items()
|
@@ -126,7 +135,7 @@ def run_ros2_tests(run):
|
|
126
135
|
},
|
127
136
|
output_path=os.path.join(run.output_path, "test_process_log.txt"),
|
128
137
|
)
|
129
|
-
except Launch_test_CmdNotFoundError
|
138
|
+
except Launch_test_CmdNotFoundError:
|
130
139
|
# raise Exception(
|
131
140
|
# f"Running {scenario['ros_testfile']} failed. Please check that the launch file exists."
|
132
141
|
# )
|
@@ -182,33 +191,40 @@ def run_ros2_tests(run):
|
|
182
191
|
for output in scenario.get("output_dirs", []):
|
183
192
|
run.log_artifacts(output)
|
184
193
|
|
185
|
-
#
|
186
|
-
|
194
|
+
# Checks for a new rosbag after test completions. We look for the directory
|
195
|
+
# as drilling down will find both the directory as well as the rosbag itself.
|
196
|
+
rosbags = [
|
197
|
+
path for path in glob("**/rosbag2*", recursive=True) if os.path.isdir(path)
|
198
|
+
]
|
187
199
|
new_rosbags = set(rosbags).difference(set(preexisting_rosbags))
|
188
200
|
from artefacts.cli.bagparser import BagFileParser
|
189
201
|
|
202
|
+
run.logger.info(f"Found new rosbags: {new_rosbags}")
|
190
203
|
if len(new_rosbags) > 0:
|
191
|
-
|
192
|
-
run.log_artifacts(
|
204
|
+
rosbag_dir = new_rosbags.pop()
|
205
|
+
run.log_artifacts(rosbag_dir, "rosbag")
|
193
206
|
if "metrics" in run.params:
|
194
|
-
#
|
195
|
-
|
207
|
+
# Search for database files in the directory
|
208
|
+
# TODO: should go inside BagFileParser?
|
209
|
+
db_files = glob(f"{rosbag_dir}/*.mcap") # Ros2 Default
|
196
210
|
if not db_files:
|
197
|
-
db_files = glob(f"{
|
211
|
+
db_files = glob(f"{rosbag_dir}/*.db3") # Legacy
|
198
212
|
if not db_files:
|
199
213
|
raise FileNotFoundError(
|
200
|
-
"No .mcap or .db3 files found in the specified path."
|
214
|
+
"No .mcap or .db3 files found in the specified path. Attempted to find in "
|
215
|
+
f"{rosbag_dir}/*.mcap and {rosbag_dir}/*.db3"
|
201
216
|
)
|
202
217
|
db_file = db_files[0]
|
218
|
+
|
203
219
|
bag = BagFileParser(db_file)
|
204
220
|
for metric in run.params["metrics"]:
|
205
221
|
try:
|
206
222
|
last_value = bag.get_last_message(metric)[1].data
|
207
223
|
run.log_metric(metric, last_value)
|
208
224
|
except KeyError:
|
209
|
-
|
225
|
+
run.logger.error(f"Metric {metric} not found in rosbag, skipping.")
|
210
226
|
except TypeError or IndexError:
|
211
|
-
|
227
|
+
run.logger.error(
|
212
228
|
f"Metric {metric} not found. Is it being published?. Skipping."
|
213
229
|
)
|
214
230
|
|
artefacts/cli/utils.py
CHANGED
@@ -8,7 +8,7 @@ import click
|
|
8
8
|
|
9
9
|
import artefacts_copava as copava
|
10
10
|
from artefacts import ARTEFACTS_DEFAULT_OUTPUT_DIR
|
11
|
-
from artefacts.cli import WarpRun
|
11
|
+
from artefacts.cli import WarpRun, localise
|
12
12
|
|
13
13
|
|
14
14
|
def run_and_save_logs(
|
@@ -74,13 +74,17 @@ def ensure_available(package: str) -> None:
|
|
74
74
|
def read_config(filename: str) -> dict:
|
75
75
|
try:
|
76
76
|
with open(filename) as f:
|
77
|
-
return copava.parse(f.read())
|
77
|
+
return copava.parse(f.read()) or {}
|
78
78
|
except FileNotFoundError:
|
79
|
-
raise click.ClickException(
|
79
|
+
raise click.ClickException(
|
80
|
+
localise(
|
81
|
+
"Project config file {file_name} not found.".format(file_name=filename)
|
82
|
+
)
|
83
|
+
)
|
80
84
|
|
81
85
|
|
82
86
|
# Click callback syntax
|
83
|
-
def config_validation(context:
|
87
|
+
def config_validation(context: click.Context, param: str, value: str) -> str:
|
84
88
|
if context.params.get("skip_validation", False):
|
85
89
|
return value
|
86
90
|
config = read_config(value)
|