• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aas-core-works / aas-core-codegen / 23051946462

13 Mar 2026 12:59PM UTC coverage: 83.657% (+1.2%) from 82.428%
23051946462

push

github

web-flow
Turn on coveralls (#596)

The site coveralls.io was down so we had to turn off the coverage
upload temporarily.

30831 of 36854 relevant lines covered (83.66%)

3.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

64.91
/aas_core_codegen/python/main.py
1
"""Generate Python code to handle AAS models based on the meta-model."""
2
import pathlib
4✔
3
from typing import TextIO, Sequence, Callable, Tuple, Optional, List
4✔
4

5
from aas_core_codegen import specific_implementations, run, intermediate
4✔
6
from aas_core_codegen.common import Error
4✔
7
from aas_core_codegen.python import (
4✔
8
    common as python_common,
9
    lib as python_lib,
10
    tests as python_tests,
11
)
12

13

14
def execute(context: run.Context, stdout: TextIO, stderr: TextIO) -> int:
4✔
15
    """Generate the code."""
16
    verified_ir_table, errors = python_lib.verify_for_types(
4✔
17
        symbol_table=context.symbol_table
18
    )
19

20
    if errors is not None:
4✔
21
        run.write_error_report(
×
22
            message=f"Failed to verify the intermediate symbol table "
23
            f"for generation of Python code"
24
            f"based on {context.model_path}",
25
            errors=[context.lineno_columner.error_message(error) for error in errors],
26
            stderr=stderr,
27
        )
28
        return 1
×
29

30
    assert verified_ir_table is not None
4✔
31

32
    unsupported_contracts_errors = (
4✔
33
        intermediate.errors_if_contracts_for_functions_or_methods_defined(
34
            verified_ir_table
35
        )
36
    )
37
    if unsupported_contracts_errors is not None:
4✔
38
        run.write_error_report(
×
39
            message=f"We do not support pre and post-conditions and snapshots "
40
            f"at the moment. Please notify the developers if you need this "
41
            f"feature (based on meta-model {context.model_path})",
42
            errors=[
43
                context.lineno_columner.error_message(error)
44
                for error in unsupported_contracts_errors
45
            ],
46
            stderr=stderr,
47
        )
48
        return 1
×
49

50
    unsupported_methods_errors = (
4✔
51
        intermediate.errors_if_non_implementation_specific_methods(verified_ir_table)
52
    )
53
    if unsupported_methods_errors is not None:
4✔
54
        run.write_error_report(
×
55
            message=f"We added some support for understood methods already and keep "
56
            f"maintaining it as it is only a matter of time when we will "
57
            f"introduce their transpilation. Introducing them after the fact "
58
            f"would have been much more difficult.\n"
59
            f"\n"
60
            f"At the given moment, however, we deliberately focus only on "
61
            f"implementation-specific methods. "
62
            f"(based on meta-model {context.model_path})",
63
            errors=[
64
                context.lineno_columner.error_message(error)
65
                for error in unsupported_methods_errors
66
            ],
67
            stderr=stderr,
68
        )
69
        return 1
×
70

71
    qualified_module_name_key = specific_implementations.ImplementationKey(
4✔
72
        "qualified_module_name.txt"
73
    )
74

75
    qualified_module_name_text = context.spec_impls.get(qualified_module_name_key, None)
4✔
76
    if qualified_module_name_text is None:
4✔
77
        stderr.write(
×
78
            f"The snippet with the qualified module name is missing: "
79
            f"{qualified_module_name_key}\n"
80
        )
81
        return 1
×
82

83
    if not python_common.QUALIFIED_MODULE_NAME_RE.fullmatch(qualified_module_name_text):
4✔
84
        stderr.write(
×
85
            f"The text from the snippet {qualified_module_name_key} "
86
            f"is not a valid qualified module name: {qualified_module_name_text!r}\n"
87
        )
88
        return 1
×
89

90
    qualified_module_name = python_common.QualifiedModuleName(
4✔
91
        qualified_module_name_text
92
    )
93

94
    verify_errors = python_lib.verify_for_verification(
4✔
95
        spec_impls=context.spec_impls,
96
        verification_functions=verified_ir_table.verification_functions,
97
    )
98

99
    if verify_errors is not None:
4✔
100
        run.write_error_report(
×
101
            message=("Failed to verify the verification functions for code generation"),
102
            errors=verify_errors,
103
            stderr=stderr,
104
        )
105
        return 1
×
106

107
    module_rel_path = pathlib.Path(qualified_module_name.replace(".", "/"))
4✔
108
    assert not module_rel_path.is_absolute()
4✔
109

110
    tests_rel_path = pathlib.Path("dev/tests")
4✔
111

112
    rel_paths_generators: Sequence[
4✔
113
        Tuple[pathlib.Path, Callable[[], Tuple[Optional[str], Optional[List[Error]]]]]
114
    ] = [
115
        (
116
            module_rel_path / "common.py",
117
            lambda: (python_lib.generate_common(), None),
118
        ),
119
        (
120
            module_rel_path / "constants.py",
121
            lambda: python_lib.generate_constants(
122
                symbol_table=context.symbol_table,
123
                qualified_module_name=qualified_module_name,
124
            ),
125
        ),
126
        (
127
            module_rel_path / "jsonization.py",
128
            lambda: python_lib.generate_jsonization(
129
                symbol_table=context.symbol_table,
130
                qualified_module_name=qualified_module_name,
131
                spec_impls=context.spec_impls,
132
            ),
133
        ),
134
        (
135
            module_rel_path / "stringification.py",
136
            lambda: python_lib.generate_stringification(
137
                symbol_table=context.symbol_table,
138
                qualified_module_name=qualified_module_name,
139
            ),
140
        ),
141
        (
142
            module_rel_path / "types.py",
143
            lambda: python_lib.generate_types(
144
                symbol_table=verified_ir_table,
145
                qualified_module_name=qualified_module_name,
146
                spec_impls=context.spec_impls,
147
            ),
148
        ),
149
        (
150
            module_rel_path / "verification.py",
151
            lambda: python_lib.generate_verification(
152
                symbol_table=verified_ir_table,
153
                qualified_module_name=qualified_module_name,
154
                spec_impls=context.spec_impls,
155
            ),
156
        ),
157
        (
158
            module_rel_path / "xmlization.py",
159
            lambda: python_lib.generate_xmlization(
160
                symbol_table=context.symbol_table,
161
                qualified_module_name=qualified_module_name,
162
                spec_impls=context.spec_impls,
163
            ),
164
        ),
165
        (
166
            tests_rel_path / "common.py",
167
            lambda: (
168
                python_tests.generate_common(
169
                    qualified_module_name=qualified_module_name
170
                ),
171
                None,
172
            ),
173
        ),
174
        (
175
            tests_rel_path / "common_jsonization.py",
176
            lambda: (
177
                python_tests.generate_common_jsonization(
178
                    symbol_table=context.symbol_table,
179
                    qualified_module_name=qualified_module_name,
180
                ),
181
                None,
182
            ),
183
        ),
184
        (
185
            tests_rel_path / "common_xmlization.py",
186
            lambda: (
187
                python_tests.generate_common_xmlization(
188
                    qualified_module_name=qualified_module_name
189
                ),
190
                None,
191
            ),
192
        ),
193
        (
194
            tests_rel_path / "test_descend_and_pass_through_visitor.py",
195
            lambda: (
196
                python_tests.generate_test_descend_and_pass_through_visitor(
197
                    qualified_module_name=qualified_module_name
198
                ),
199
                None,
200
            ),
201
        ),
202
        (
203
            tests_rel_path / "test_descend_once.py",
204
            lambda: (
205
                python_tests.generate_test_descend_once(
206
                    qualified_module_name=qualified_module_name
207
                ),
208
                None,
209
            ),
210
        ),
211
        (
212
            tests_rel_path / "test_for_over_X_or_empty.py",
213
            lambda: (
214
                python_tests.generate_test_for_over_x_or_empty(
215
                    symbol_table=context.symbol_table,
216
                    qualified_module_name=qualified_module_name,
217
                ),
218
                None,
219
            ),
220
        ),
221
        (
222
            tests_rel_path / "test_for_x_or_default.py",
223
            lambda: (
224
                python_tests.generate_test_for_x_or_default(
225
                    symbol_table=context.symbol_table,
226
                    qualified_module_name=qualified_module_name,
227
                ),
228
                None,
229
            ),
230
        ),
231
        (
232
            tests_rel_path / "test_jsonization_of_classes_with_descendants.py",
233
            lambda: (
234
                python_tests.generate_test_jsonization_of_classes_with_descendants(
235
                    symbol_table=context.symbol_table,
236
                    qualified_module_name=qualified_module_name,
237
                ),
238
                None,
239
            ),
240
        ),
241
        (
242
            tests_rel_path / "test_jsonization_of_concrete_classes.py",
243
            lambda: (
244
                python_tests.generate_test_jsonization_of_concrete_classes(
245
                    symbol_table=context.symbol_table,
246
                    qualified_module_name=qualified_module_name,
247
                ),
248
                None,
249
            ),
250
        ),
251
        (
252
            tests_rel_path / "test_jsonization_of_enums.py",
253
            lambda: (
254
                python_tests.generate_test_jsonization_of_enums(
255
                    symbol_table=context.symbol_table,
256
                    qualified_module_name=qualified_module_name,
257
                ),
258
                None,
259
            ),
260
        ),
261
        (
262
            tests_rel_path / "test_xmlization_of_classes_with_descendants.py",
263
            lambda: (
264
                python_tests.generate_test_xmlization_of_classes_with_descendants(
265
                    symbol_table=context.symbol_table,
266
                    qualified_module_name=qualified_module_name,
267
                ),
268
                None,
269
            ),
270
        ),
271
        (
272
            tests_rel_path / "test_xmlization_of_concrete_classes.py",
273
            lambda: (
274
                python_tests.generate_test_xmlization_of_concrete_classes(
275
                    symbol_table=context.symbol_table,
276
                    qualified_module_name=qualified_module_name,
277
                ),
278
                None,
279
            ),
280
        ),
281
    ]
282

283
    for rel_path, generator_func in rel_paths_generators:
4✔
284
        assert not rel_path.is_absolute()
4✔
285

286
        code, errors = generator_func()
4✔
287

288
        if errors is not None:
4✔
289
            run.write_error_report(
×
290
                message=f"Failed to generate {rel_path} "
291
                f"based on {context.model_path}",
292
                errors=[
293
                    context.lineno_columner.error_message(error) for error in errors
294
                ],
295
                stderr=stderr,
296
            )
297
            return 1
×
298

299
        assert code is not None
4✔
300

301
        pth = context.output_dir / rel_path
4✔
302

303
        try:
4✔
304
            pth.parent.mkdir(parents=True, exist_ok=True)
4✔
305
        except Exception as exception:
×
306
            run.write_error_report(
×
307
                message=f"Failed to create the directory {pth.parent}",
308
                errors=[str(exception)],
309
                stderr=stderr,
310
            )
311
            return 1
×
312

313
        # NOTE (mristin):
314
        # We add this type check since we had many problems during the development.
315
        assert isinstance(
4✔
316
            code, str
317
        ), f"Unexpected code {code} for the generator for {rel_path}"
318

319
        try:
4✔
320
            pth.write_text(code, encoding="utf-8")
4✔
321
        except Exception as exception:
×
322
            run.write_error_report(
×
323
                message=f"Failed to write to {pth}",
324
                errors=[str(exception)],
325
                stderr=stderr,
326
            )
327
            return 1
×
328

329
    stdout.write(f"Code generated to: {context.output_dir}\n")
4✔
330
    return 0
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc