can-api-generator 2.4.0__tar.gz → 2.5.0__tar.gz
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.
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/PKG-INFO +24 -1
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/README.md +22 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/pyproject.toml +1 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/__about__.py +1 -1
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/main.py +70 -22
- can_api_generator-2.5.0/tests/test_config_file.py +68 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/.gitignore +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/Advantics_Bootloader.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/LICENSE.txt +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/manual_api_test.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/manual_api_test.h +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/manual_api_test.o +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/manual_cag_test.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/__init__.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/cbdb_generator.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/code_generator.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/msg_processor.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/callback_macros.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/canframe.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/declaration_macros.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/dyndec_header.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/dyndec_source.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/encoding_macros.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/header_template.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/rx_macros.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/source_template.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/tx_macros.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/types.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/utils.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_1_rx_over_can +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_api.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_api.h +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_kcd_api_test_mux_with_same_signal_names_labeled_mux_variants.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_mux_with_same_signal_names_labeled_mux_variants.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_mux_with_same_signal_names_labeled_mux_variants.h +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_test_1_rx_over_can.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_test_basic_multiplex_rx_over_can.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_test_mux_with_partially_labled_index_rx_over_can.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/test_test_mux_with_same_signal_names_labeled_mux_variants_rx_over_can.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/__init__.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/cantool_test_utils.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/compat_shim.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/dyndec_test_harness.c +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/multiple_busses_test.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_1.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_basic_multiplex.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_big_endian.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_can_db_model_dep.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_cbdb_generator.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_cli.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_cross_interface_compat.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_cross_interface_compat.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_dyndec_round_trip.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_float_wrong_length.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_message_parser.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_missing_consumer.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_missing_producer.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_group_count_out_of_order.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_labeled_index.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_partially_labled_index.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_same_signal_names.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_same_signal_names_labeled_mux_variants.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_scale_and_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_non_encodable_0.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_overlapping_signals.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_periodic_tx_over_can.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_procedures.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_prog_source_template.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_rx_over_can.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_direction.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/double_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/double_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/double_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/float_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/float_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/float_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_matching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_matching_fractional_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_matching_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_matching_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_matching_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_nonmatching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_nonmatching_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_nonmatching_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/sint_nonmatching_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/test_decoding_numerical_value.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/test_encoding_numerical_value.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/test_signal_encoding_wrong_float_size.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_matching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_matching_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_matching_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_matching_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_nonmatching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_nonmatching_plain.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_nonmatching_scaled.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/uint_nonmatching_scaled_offset.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_info.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_time_callback_arg.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_too_large_message.kcd +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_tx_function.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_tx_over_can.jinja +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_utils.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_vcan_round_trip.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_yaml_cbdb.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_yaml_input.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_yaml_kcd_equivalence.py +0 -0
- {can_api_generator-2.4.0 → can_api_generator-2.5.0}/todo.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: can-api-generator
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Program to generate a 'signal' style CAN API in C
|
|
5
5
|
Project-URL: Documentation, https://sr.ht/~laplace/can-api-generator#readme
|
|
6
6
|
Project-URL: Issues, https://sr.ht/~laplace/can-api-generator/issues
|
|
@@ -20,6 +20,7 @@ Requires-Dist: can-db-model>=0.1
|
|
|
20
20
|
Requires-Dist: cantools
|
|
21
21
|
Requires-Dist: click
|
|
22
22
|
Requires-Dist: jinja2
|
|
23
|
+
Requires-Dist: pyyaml
|
|
23
24
|
Requires-Dist: rich
|
|
24
25
|
Description-Content-Type: text/markdown
|
|
25
26
|
|
|
@@ -56,6 +57,7 @@ Description-Content-Type: text/markdown
|
|
|
56
57
|
- [`api`](#api)
|
|
57
58
|
- [`cbdb`](#cbdb)
|
|
58
59
|
- [`dyndec`](#dyndec)
|
|
60
|
+
- [Config file](#config-file)
|
|
59
61
|
|
|
60
62
|
## Installation
|
|
61
63
|
|
|
@@ -610,6 +612,7 @@ to a mux group. The message list is followed immediately by that message's signa
|
|
|
610
612
|
## Command-line reference
|
|
611
613
|
|
|
612
614
|
All generation is done through subcommands of `can-api-gen`. Run `can-api-gen COMMAND --help` for the authoritative option list.
|
|
615
|
+
Every command also accepts `--config FILE`; see [Config file](#config-file).
|
|
613
616
|
|
|
614
617
|
### `api`
|
|
615
618
|
|
|
@@ -715,3 +718,23 @@ Options:
|
|
|
715
718
|
* `-lm`, `--length-member-name TEXT` — override the name of the `CanFrame` length member (default `length`).
|
|
716
719
|
* `-pm`, `--payload-member-name TEXT` — override the name of the `CanFrame` payload member (default `payload`).
|
|
717
720
|
* `--help` — show the CLI help and exit.
|
|
721
|
+
|
|
722
|
+
### Config file
|
|
723
|
+
|
|
724
|
+
Instead of repeating a long flag list, put the options in a YAML file and pass it with `--config FILE` to any command. The file has one section per command, so
|
|
725
|
+
one file can serve `api`, `cbdb` and `dyndec`; a command reads only its own section. Keys are the long option names without the leading `--` (dashes or
|
|
726
|
+
underscores both work), and values are the option values (`true`/`false` for flags):
|
|
727
|
+
|
|
728
|
+
```yaml
|
|
729
|
+
api:
|
|
730
|
+
periodic-tx: true
|
|
731
|
+
tx-signal-store: true
|
|
732
|
+
time-as-tx-callback-arg: true
|
|
733
|
+
id-member-name: can_id
|
|
734
|
+
dyndec:
|
|
735
|
+
id-member-name: can_id
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
Anything given on the command line overrides the file. Every flag has a `--no-` form for this, e.g.
|
|
739
|
+
`can-api-gen api --config can.yaml --no-tx-signal-store db.kcd my_api DUT`. Positional arguments (`DB_FILE`, `LIBRARY_NAME`, `NODE_NAME`, …) always come from
|
|
740
|
+
the command line. An unknown key or an invalid value is an error.
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
- [`api`](#api)
|
|
32
32
|
- [`cbdb`](#cbdb)
|
|
33
33
|
- [`dyndec`](#dyndec)
|
|
34
|
+
- [Config file](#config-file)
|
|
34
35
|
|
|
35
36
|
## Installation
|
|
36
37
|
|
|
@@ -585,6 +586,7 @@ to a mux group. The message list is followed immediately by that message's signa
|
|
|
585
586
|
## Command-line reference
|
|
586
587
|
|
|
587
588
|
All generation is done through subcommands of `can-api-gen`. Run `can-api-gen COMMAND --help` for the authoritative option list.
|
|
589
|
+
Every command also accepts `--config FILE`; see [Config file](#config-file).
|
|
588
590
|
|
|
589
591
|
### `api`
|
|
590
592
|
|
|
@@ -690,3 +692,23 @@ Options:
|
|
|
690
692
|
* `-lm`, `--length-member-name TEXT` — override the name of the `CanFrame` length member (default `length`).
|
|
691
693
|
* `-pm`, `--payload-member-name TEXT` — override the name of the `CanFrame` payload member (default `payload`).
|
|
692
694
|
* `--help` — show the CLI help and exit.
|
|
695
|
+
|
|
696
|
+
### Config file
|
|
697
|
+
|
|
698
|
+
Instead of repeating a long flag list, put the options in a YAML file and pass it with `--config FILE` to any command. The file has one section per command, so
|
|
699
|
+
one file can serve `api`, `cbdb` and `dyndec`; a command reads only its own section. Keys are the long option names without the leading `--` (dashes or
|
|
700
|
+
underscores both work), and values are the option values (`true`/`false` for flags):
|
|
701
|
+
|
|
702
|
+
```yaml
|
|
703
|
+
api:
|
|
704
|
+
periodic-tx: true
|
|
705
|
+
tx-signal-store: true
|
|
706
|
+
time-as-tx-callback-arg: true
|
|
707
|
+
id-member-name: can_id
|
|
708
|
+
dyndec:
|
|
709
|
+
id-member-name: can_id
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
Anything given on the command line overrides the file. Every flag has a `--no-` form for this, e.g.
|
|
713
|
+
`can-api-gen api --config can.yaml --no-tx-signal-store db.kcd my_api DUT`. Positional arguments (`DB_FILE`, `LIBRARY_NAME`, `NODE_NAME`, …) always come from
|
|
714
|
+
the command line. An unknown key or an invalid value is an error.
|
|
@@ -12,6 +12,51 @@ from can_api_generator.cbdb_generator import generate_cbdb, build_sidecar, CbdbG
|
|
|
12
12
|
from can_api_generator.utils import converrt_to_c_identifier
|
|
13
13
|
from jinja2 import Environment, FileSystemLoader
|
|
14
14
|
from pathlib import Path
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _load_config(ctx, param, value):
|
|
19
|
+
"""Turn the command's section of a YAML config file into click defaults.
|
|
20
|
+
|
|
21
|
+
The file maps command names to option tables, e.g. {"api": {"periodic-tx":
|
|
22
|
+
true}}. Keys are long option names (dashes or underscores). The values
|
|
23
|
+
become ctx.default_map, so every option given on the command line still
|
|
24
|
+
takes precedence over the file.
|
|
25
|
+
"""
|
|
26
|
+
if value is None:
|
|
27
|
+
return
|
|
28
|
+
try:
|
|
29
|
+
with open(value) as config_file:
|
|
30
|
+
data = yaml.safe_load(config_file)
|
|
31
|
+
except (OSError, yaml.YAMLError) as e:
|
|
32
|
+
raise click.BadParameter(f"cannot read config file: {e}", ctx, param)
|
|
33
|
+
if data is None:
|
|
34
|
+
data = {}
|
|
35
|
+
if not isinstance(data, dict):
|
|
36
|
+
raise click.BadParameter(
|
|
37
|
+
"the config file must map command names to option tables", ctx, param)
|
|
38
|
+
section = data.get(ctx.info_name) or {}
|
|
39
|
+
if not isinstance(section, dict):
|
|
40
|
+
raise click.BadParameter(
|
|
41
|
+
f"section '{ctx.info_name}' must map option names to values", ctx, param)
|
|
42
|
+
known = {p.name for p in ctx.command.params
|
|
43
|
+
if isinstance(p, click.Option) and p.name != "config"}
|
|
44
|
+
defaults = {}
|
|
45
|
+
for key, option_value in section.items():
|
|
46
|
+
name = str(key).replace("-", "_")
|
|
47
|
+
if name not in known:
|
|
48
|
+
raise click.BadParameter(
|
|
49
|
+
f"unknown option '{key}' in section '{ctx.info_name}'", ctx, param)
|
|
50
|
+
defaults[name] = option_value
|
|
51
|
+
ctx.default_map = {**(ctx.default_map or {}), **defaults}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
config_option = click.option(
|
|
55
|
+
"--config", type=click.Path(exists=True, dir_okay=False),
|
|
56
|
+
is_eager=True, expose_value=False, callback=_load_config,
|
|
57
|
+
help="YAML file providing defaults for this command's options, under a "
|
|
58
|
+
"section named after the command (api, cbdb, dyndec). Options given "
|
|
59
|
+
"on the command line override the file.")
|
|
15
60
|
|
|
16
61
|
|
|
17
62
|
@click.group()
|
|
@@ -23,13 +68,14 @@ def main():
|
|
|
23
68
|
|
|
24
69
|
|
|
25
70
|
@main.command()
|
|
71
|
+
@config_option
|
|
26
72
|
@click.argument("DB_File", type=click.Path(exists=True, dir_okay=False),
|
|
27
73
|
required=True, nargs=1)
|
|
28
74
|
@click.argument("Library_Name", type=str, required=True)
|
|
29
75
|
@click.argument("Node_Name", type=str, required=True)
|
|
30
|
-
@click.option("-f", "--force",
|
|
76
|
+
@click.option("-f", "--force/--no-force", required=False, default=False,
|
|
31
77
|
help="Overwrite existing output files")
|
|
32
|
-
@click.option("-a", "--encode-all-signals-func",
|
|
78
|
+
@click.option("-a", "--encode-all-signals-func/--no-encode-all-signals-func", default=False,
|
|
33
79
|
help="Generate a function for each message that encodes every signal into frames at least once,"
|
|
34
80
|
" this is helpful when some signals are inside of a mux, but all signals need to be sent "
|
|
35
81
|
" regardless of how many frames need to be encoded to send the state of each signal at least"
|
|
@@ -50,74 +96,74 @@ def main():
|
|
|
50
96
|
@click.option("-pm", "--payload-member-name", type=str, default="payload",
|
|
51
97
|
help="The name of the CanFrame struct member that holds the "
|
|
52
98
|
"payload as uint64")
|
|
53
|
-
@click.option("-r", "--global-rx",
|
|
99
|
+
@click.option("-r", "--global-rx/--no-global-rx", default=False,
|
|
54
100
|
help="Generate a function and api-wide struct that updates an"
|
|
55
101
|
" api message struct upon reception of a matching frame")
|
|
56
|
-
@click.option("-p", "--periodic-tx",
|
|
102
|
+
@click.option("-p", "--periodic-tx/--no-periodic-tx", default=False,
|
|
57
103
|
help="Generate code that will define a TX struct as well as a function "
|
|
58
104
|
"that periodically sends the messages according to their "
|
|
59
105
|
"periodicity")
|
|
60
|
-
@click.option("--ti-compatible",
|
|
106
|
+
@click.option("--ti-compatible/--no-ti-compatible", default=False,
|
|
61
107
|
help="Generate C code that can be compiled using the TI C2000 compiler"
|
|
62
108
|
" The TI compiler does not handle variable declarations inside of case"
|
|
63
109
|
" blocks so the variable declaration is moved to the top of a switch")
|
|
64
|
-
@click.option("--send-now",
|
|
110
|
+
@click.option("--send-now/--no-send-now", default=False,
|
|
65
111
|
help="Add mechanism in to the periodic tx function that allows to immediately "
|
|
66
112
|
"send a message even if it is not enabled or has just been sent."
|
|
67
113
|
" This is useful for updating critical signals as early as possible after a change")
|
|
68
|
-
@click.option("--double-buffered",
|
|
114
|
+
@click.option("--double-buffered/--no-double-buffered", default=False,
|
|
69
115
|
help="Generate double-buffered signal storage so that an ISR can safely decode"
|
|
70
116
|
" RX frames without exposing a partially-decoded struct to readers, and so"
|
|
71
117
|
" that user code can stage TX signal updates without racing the periodic TX"
|
|
72
118
|
" encoder. Swaps are performed via per-message pointer swaps; an explicit"
|
|
73
119
|
" <api>_<msg>_commit call is required to publish staged TX values.")
|
|
74
|
-
@click.option("--rx-callback-context",
|
|
120
|
+
@click.option("--rx-callback-context/--no-rx-callback-context", default=False,
|
|
75
121
|
help="Add a void *rx_callback_context field to MsgRxContext and "
|
|
76
122
|
"pass it as the sole argument to the RX callback, widening "
|
|
77
123
|
"its signature to void (*rx_callback)(void *).")
|
|
78
|
-
@click.option("--tx-callback-context",
|
|
124
|
+
@click.option("--tx-callback-context/--no-tx-callback-context", default=False,
|
|
79
125
|
help="Add a void *tx_callback_context field to MsgTxContext and "
|
|
80
126
|
"pass it as the sole argument to the TX callback, widening "
|
|
81
127
|
"its signature to void (*tx_callback)(void *).")
|
|
82
|
-
@click.option("--msg-as-rx-callback-arg",
|
|
128
|
+
@click.option("--msg-as-rx-callback-arg/--no-msg-as-rx-callback-arg", default=False,
|
|
83
129
|
help="Pass a void * to the message's just-decoded signal struct "
|
|
84
130
|
"as the first argument to the RX callback. Composes with "
|
|
85
131
|
"--rx-callback-context, which appends the context pointer as "
|
|
86
132
|
"a second argument. Only meaningful together with -r.")
|
|
87
|
-
@click.option("--rx-signal-store",
|
|
133
|
+
@click.option("--rx-signal-store/--no-rx-signal-store", default=False,
|
|
88
134
|
help="Generate a permanent per-message RX signal store in the "
|
|
89
135
|
"global RX struct (the default before v2.0). Without it, "
|
|
90
136
|
"global RX is callback-only: decoded signals reach the "
|
|
91
137
|
"application solely through the per-message RX callback and "
|
|
92
138
|
"are never stored. Only meaningful together with -r.")
|
|
93
|
-
@click.option("--with-rx-valid",
|
|
139
|
+
@click.option("--with-rx-valid/--no-with-rx-valid", default=False,
|
|
94
140
|
help="In callback-only mode (no --rx-signal-store), add a valid "
|
|
95
141
|
"field to MsgRxContext and set it on each matched frame, for "
|
|
96
142
|
"struct-layout compatibility with store-based APIs. No effect "
|
|
97
143
|
"when --rx-signal-store is set.")
|
|
98
|
-
@click.option("--msg-as-tx-callback-arg",
|
|
144
|
+
@click.option("--msg-as-tx-callback-arg/--no-msg-as-tx-callback-arg", default=False,
|
|
99
145
|
help="Pass a void * to the message's store struct (the one about "
|
|
100
146
|
"to be encoded) as the first argument to the TX callback. "
|
|
101
147
|
"Composes with --tx-callback-context, which appends the "
|
|
102
148
|
"context pointer as a second argument. Only meaningful "
|
|
103
149
|
"together with -p.")
|
|
104
|
-
@click.option("--tx-signal-store",
|
|
150
|
+
@click.option("--tx-signal-store/--no-tx-signal-store", default=False,
|
|
105
151
|
help="Generate a permanent per-message TX signal store in the "
|
|
106
152
|
"periodic-TX struct (the default before v2.0). Without it, "
|
|
107
153
|
"periodic TX is callback-only: each scheduled message's "
|
|
108
154
|
"callback returns the struct to encode, and a NULL return or "
|
|
109
155
|
"missing callback sends nothing. Only meaningful with -p.")
|
|
110
|
-
@click.option("--time-as-rx-callback-arg",
|
|
156
|
+
@click.option("--time-as-rx-callback-arg/--no-time-as-rx-callback-arg", default=False,
|
|
111
157
|
help="Pass the current time (the now argument of "
|
|
112
158
|
"<api>_process_received_frame) to the RX callback as a "
|
|
113
159
|
"uint64_t, after the message pointer and before the context "
|
|
114
160
|
"pointer. Only meaningful together with -r.")
|
|
115
|
-
@click.option("--time-as-tx-callback-arg",
|
|
161
|
+
@click.option("--time-as-tx-callback-arg/--no-time-as-tx-callback-arg", default=False,
|
|
116
162
|
help="Pass the current time (the now argument of "
|
|
117
163
|
"<api>_periodic_tx) to the TX callback as a uint64_t, after "
|
|
118
164
|
"the message pointer and before the context pointer. Only "
|
|
119
165
|
"meaningful together with -p.")
|
|
120
|
-
@click.option("--tx-function",
|
|
166
|
+
@click.option("--tx-function/--no-tx-function", default=False,
|
|
121
167
|
help="Bind a frame sink to the periodic-TX API instead of "
|
|
122
168
|
"returning one frame per call. <api>_periodic_tx_init takes "
|
|
123
169
|
"a uint16_t (*tx_function)(void *, const <frame> *) and its "
|
|
@@ -125,18 +171,18 @@ def main():
|
|
|
125
171
|
"due message to it in a single pass and returns the number "
|
|
126
172
|
"accepted. A 0 return leaves last_tx and send_now untouched, "
|
|
127
173
|
"so the message is retried. Only meaningful with -p.")
|
|
128
|
-
@click.option("--prefix-signal-struct-names",
|
|
174
|
+
@click.option("--prefix-signal-struct-names/--no-prefix-signal-struct-names", default=False,
|
|
129
175
|
help="Prefix every per-message signal struct type name with the "
|
|
130
176
|
"CamelCase API prefix (the same prefix used for "
|
|
131
177
|
"<Prefix>RxSignals / <Prefix>TxSignals), so two similar APIs "
|
|
132
178
|
"(e.g. two versions of a database) can coexist in one "
|
|
133
179
|
"translation unit with distinct struct names.")
|
|
134
|
-
@click.option("--prefix-context-struct-names",
|
|
180
|
+
@click.option("--prefix-context-struct-names/--no-prefix-context-struct-names", default=False,
|
|
135
181
|
help="Prefix the MsgRxContext / MsgTxContext struct type names (and "
|
|
136
182
|
"their include-guard tokens) with the CamelCase API prefix, so "
|
|
137
183
|
"context structs from two coexisting APIs do not share one "
|
|
138
184
|
"definition.")
|
|
139
|
-
@click.option("-v", "--verbose",
|
|
185
|
+
@click.option("-v", "--verbose/--no-verbose", default=False,
|
|
140
186
|
help="Print the Data that is passed to the template that "
|
|
141
187
|
"generates the code")
|
|
142
188
|
def api(db_file, library_name, node_name, force, encode_all_signals_func,
|
|
@@ -228,10 +274,11 @@ def api(db_file, library_name, node_name, force, encode_all_signals_func,
|
|
|
228
274
|
|
|
229
275
|
|
|
230
276
|
@main.command()
|
|
277
|
+
@config_option
|
|
231
278
|
@click.argument("DB_File", type=click.Path(exists=True, dir_okay=False),
|
|
232
279
|
required=True, nargs=1)
|
|
233
280
|
@click.argument("Output_Base", type=str, required=True)
|
|
234
|
-
@click.option("-f", "--force",
|
|
281
|
+
@click.option("-f", "--force/--no-force", required=False, default=False,
|
|
235
282
|
help="Overwrite existing output files")
|
|
236
283
|
def cbdb(db_file, output_base, force):
|
|
237
284
|
"""
|
|
@@ -267,8 +314,9 @@ def cbdb(db_file, output_base, force):
|
|
|
267
314
|
|
|
268
315
|
|
|
269
316
|
@main.command()
|
|
317
|
+
@config_option
|
|
270
318
|
@click.argument("Library_Name", type=str, required=True)
|
|
271
|
-
@click.option("-f", "--force",
|
|
319
|
+
@click.option("-f", "--force/--no-force", required=False, default=False,
|
|
272
320
|
help="Overwrite existing output files")
|
|
273
321
|
@click.option("-im", "--id-member-name", type=str, default="arbitration_id",
|
|
274
322
|
help="The name of the CanFrame struct member that holds the "
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""--config: YAML defaults per command, overridden by the command line."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from click.testing import CliRunner
|
|
5
|
+
|
|
6
|
+
from src.can_api_generator.main import main
|
|
7
|
+
|
|
8
|
+
CONFIG = """\
|
|
9
|
+
api:
|
|
10
|
+
periodic-tx: true
|
|
11
|
+
tx_signal_store: true
|
|
12
|
+
time-as-tx-callback-arg: true
|
|
13
|
+
id-member-name: can_id
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _run(tmp_path, monkeypatch, config, *args):
|
|
18
|
+
kcd = str(Path("tests/test_1.kcd").resolve())
|
|
19
|
+
monkeypatch.chdir(tmp_path)
|
|
20
|
+
(tmp_path / "cfg.yaml").write_text(config)
|
|
21
|
+
return CliRunner().invoke(
|
|
22
|
+
main, ["api", "--config", "cfg.yaml", kcd, "cf", "DUT", "-f", *args])
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_config_provides_options(tmp_path, monkeypatch):
|
|
26
|
+
result = _run(tmp_path, monkeypatch, CONFIG)
|
|
27
|
+
assert result.exit_code == 0, result.output
|
|
28
|
+
header = (tmp_path / "cf.h").read_text()
|
|
29
|
+
source = (tmp_path / "cf.c").read_text()
|
|
30
|
+
assert "struct Message2 message_2_signals;" in header
|
|
31
|
+
assert "void *(*tx_callback)(uint64_t);" in header
|
|
32
|
+
assert "output_frame->can_id = 0x1;" in source
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_command_line_overrides_config(tmp_path, monkeypatch):
|
|
36
|
+
result = _run(tmp_path, monkeypatch, CONFIG,
|
|
37
|
+
"--no-tx-signal-store", "-im", "arb")
|
|
38
|
+
assert result.exit_code == 0, result.output
|
|
39
|
+
header = (tmp_path / "cf.h").read_text()
|
|
40
|
+
source = (tmp_path / "cf.c").read_text()
|
|
41
|
+
assert "message_2_signals" not in header
|
|
42
|
+
assert "output_frame->arb = 0x1;" in source
|
|
43
|
+
# untouched config values still apply
|
|
44
|
+
assert "(uint64_t)" in header
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_config_section_of_other_command_ignored(tmp_path, monkeypatch):
|
|
48
|
+
result = _run(tmp_path, monkeypatch, "dyndec:\n force: true\n", "-p")
|
|
49
|
+
assert result.exit_code == 0, result.output
|
|
50
|
+
assert "arbitration_id" in (tmp_path / "cf.c").read_text()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_config_unknown_option_rejected(tmp_path, monkeypatch):
|
|
54
|
+
result = _run(tmp_path, monkeypatch, "api:\n bogus-flag: true\n")
|
|
55
|
+
assert result.exit_code == 2
|
|
56
|
+
assert "unknown option 'bogus-flag'" in result.output
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_config_invalid_value_rejected(tmp_path, monkeypatch):
|
|
60
|
+
result = _run(tmp_path, monkeypatch, "api:\n periodic-tx: maybe\n")
|
|
61
|
+
assert result.exit_code == 2
|
|
62
|
+
assert "periodic-tx" in result.output
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_config_not_a_mapping_rejected(tmp_path, monkeypatch):
|
|
66
|
+
result = _run(tmp_path, monkeypatch, "- 1\n")
|
|
67
|
+
assert result.exit_code == 2
|
|
68
|
+
assert "must map command names" in result.output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/canframe.jinja
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/rx_macros.jinja
RENAMED
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/src/can_api_generator/templates/tx_macros.jinja
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_group_count_out_of_order.kcd
RENAMED
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_partially_labled_index.kcd
RENAMED
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_same_signal_names.kcd
RENAMED
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_mux_with_scale_and_offset.kcd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/double_plain.kcd
RENAMED
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/double_scaled.kcd
RENAMED
|
File without changes
|
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/float_plain.kcd
RENAMED
|
File without changes
|
{can_api_generator-2.4.0 → can_api_generator-2.5.0}/tests/test_signal_encoding/float_scaled.kcd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|