Skip to content

Commit a1a9c8b

Browse files
Remove default check for is_set (#61)
* Remove automatically checking for is_set. Now only explicit is_set rules are checked. Also, is_valid does not generate a warning for a rule violation of a subfield. This is somewhat redundant. * Set OSI submodule to according branch * Add option to rules2yml to add is_set rule to all fields for a full interface check. The documentation has been adjusted accordingly * Add comment to restructure subfield iteration * Change trace file to a one with more test cases. Remove txt trace file * Update osi submodule to current master branch * Rename is_valid to check_children, because outputting a validity warning for every field with non-valid sub-fields does not make any sense and clutters up the warning output. * Adjusted usage documentation according to the changes * Fix call to rule_checker * Fix doc references to example trace file * Fix example trace file name * Remove parallel example from usage doc --------- Signed-off-by: ClemensLinnhoff <[email protected]>
1 parent 71e8e24 commit a1a9c8b

11 files changed

+113
-448
lines changed

Diff for: .github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,5 @@ jobs:
7878
run: |
7979
source .venv/bin/activate
8080
pip install .
81-
osivalidator --data data/20210818T150542Z_sv_312_50_one_moving_object.osi -r rules
82-
osivalidator --data data/20210818T150542Z_sv_312_50_one_moving_object.osi -r rules --parallel
81+
osivalidator --data data/20240221T141700Z_sv_300_2112_10_one_moving_object.osi -r rules
82+
osivalidator --data data/20240221T141700Z_sv_300_2112_10_one_moving_object.osi -r rules --parallel

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,5 @@ $ source .venv/Scripts/activate
8080
## Example command
8181
8282
```bash
83-
$ osivalidator --data data/20210818T150542Z_sv_312_50_one_moving_object.osi --rules rules/
83+
$ osivalidator --data data/20240221T141700Z_sv_300_2112_10_one_moving_object.osi --rules rules/
8484
```
-5.94 KB
Binary file not shown.
1.26 KB
Binary file not shown.

Diff for: doc/usage.adoc

+37-302
Large diffs are not rendered by default.

Diff for: doc/writing-rules.adoc

+38-17
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,37 @@
22

33
== Folder structure
44

5-
Currently the rules are contained in `+*.yml+` files in the folder
6-
https://github.com/OpenSimulationInterface/osi-validation/tree/master/rules[rules].
7-
The organization of the files in this folder follows the architecture of
8-
OSI for consistency. In the future the rules will be ported directly
9-
into the `+*.proto+` files of
5+
Official rules for individual OSI fields are defined in the `+*.proto+` files of
106
https://github.com/OpenSimulationInterface/open-simulation-interface[OSI].
7+
The first step to using and editing rules is to extract them from the proto files with `+rules2yml.py+`.
8+
It has the following options:
9+
[source,bash]
10+
----
11+
usage: python3 rules2yml.py [-h] [--dir DIR] [--full-osi]
12+
13+
Export the rules of *.proto files into the *.yml format so it can be used by
14+
the validator.
15+
16+
options:
17+
-h, --help show this help message and exit
18+
--dir DIR, -d DIR Name of the directory where the yml rules will be stored.
19+
--full-osi, -f Add is_set rule to all fields that do not contain it already.
20+
----
21+
22+
The following example command will generate the yml rule files in a folder `rules` and add the `is_set` rule to every OSI field that does not have this rule anyways.
23+
This will result in a rule base to check for a full interface.
24+
25+
[source,bash]
26+
----
27+
python3 rules2yml.py --dir rules --full-osi
28+
----
29+
30+
The resulting yml rule files can be freely edited and are explained in the following in more detail.
1131

1232
== File structure
1333

14-
Below you can see an example of the
15-
https://github.com/OpenSimulationInterface/osi-validation/blob/master/rules/osi_detectedlane.yml[osi_detectedlane.yml]
16-
rule file for
17-
https://github.com/OpenSimulationInterface/open-simulation-interface/blob/master/osi_detectedlane.proto[osi_detectedlane.proto]:
34+
Below you can see an example of the osi_detectedlane.yml rule file for
35+
https://github.com/OpenSimulationInterface/open-simulation-interface/blob/master/osi_detectedlane.proto[osi_detectedlane.proto] without the `--full-osi` option.
1836

1937
[source,YAML]
2038
----
@@ -46,10 +64,11 @@ apply to that specific field. For example the probability of the message
4664

4765
The rules can either be with or without any parameters.
4866

49-
....
67+
[source,YAML]
68+
----
5069
is_greater_than_or_equal_to: 0.0
5170
is_equal: 1
52-
....
71+
----
5372

5473
In the case a rule has a parameter, it is written as a
5574
[.title-ref]#mapping# ( a [.title-ref]#scalar# followed by a colon ":").
@@ -62,15 +81,16 @@ https://github.com/OpenSimulationInterface/osi-validation/blob/master/osivalidat
6281
See also examples for available rules which can be defined in `+*.yml+`
6382
files below:
6483

65-
[source,python]
84+
[source,YAML]
6685
----
86+
is_set:
6787
is_greater_than: 1
6888
is_greater_than_or_equal_to: 1
6989
is_less_than_or_equal_to: 10
7090
is_less_than: 2
7191
is_equal: 1
7292
is_different: 2
73-
is_globally_unique
93+
is_globally_unique:
7494
refers_to: Lane
7595
is_iso_country_code:
7696
first_element: {is_equal: 0.13, is_greater_than: 0.13}
@@ -80,12 +100,13 @@ check_if: [{is_equal: 2, is_greater_than: 3, target: this.y}, {do_check: {is_equ
80100

81101
== Severity
82102

83-
When an attribute does not comply with a rule, a Warning is throw. An
84-
Error will be throw if an exclamation mark is written at the end of the
103+
When an attribute does not comply with a rule, a warning is thrown. An
104+
error will be thrown if an exclamation mark is written at the end of the
85105
verb of a rule.
86106

87107
=== Example
88108

89-
....
109+
[source,YAML]
110+
----
90111
is_greater_than!: 0
91-
....
112+
----

Diff for: open-simulation-interface

Diff for: osivalidator/osi_general_validator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def process_message(message, timestep, data_type):
184184
LOGGER.info(None, f"Analyze message of timestamp {timestamp}", False)
185185

186186
# Check common rules
187-
getattr(rule_checker, "is_valid")(
187+
getattr(rule_checker, "check_children")(
188188
linked_proto_field.LinkedProtoField(message, name=data_type),
189189
VALIDATION_RULES.get_rules().get_type(data_type),
190190
)

Diff for: osivalidator/osi_rules_implementations.py

+4-13
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,7 @@ def add_default_rules_to_subfields(message, type_rules):
2424
)
2525

2626
if descriptor.message_type:
27-
field_rules.add_rule(osi_rules.Rule(verb="is_valid"))
28-
29-
is_set_severity = (
30-
osi_rules.Severity.WARN
31-
if field_rules.has_rule("is_optional")
32-
else osi_rules.Severity.ERROR
33-
)
34-
35-
field_rules.add_rule(osi_rules.Rule(verb="is_set", severity=is_set_severity))
27+
field_rules.add_rule(osi_rules.Rule(verb="check_children"))
3628

3729

3830
# DECORATORS
@@ -100,7 +92,7 @@ def wrapper(self, field, rule, **kwargs):
10092

10193

10294
@rule_implementation
103-
def is_valid(self, field, rule):
95+
def check_children(self, field, rule):
10496
"""Check if a field message is valid, that is all the inner rules of the
10597
message in the field are complying.
10698
@@ -122,20 +114,19 @@ def is_valid(self, field, rule):
122114
else:
123115
subfield_rules = rule.root.get_type(field.message_type)
124116

125-
result = True
126117
# Add default rules for each subfield that can be validated (default)
127118
add_default_rules_to_subfields(field, subfield_rules)
128119

129120
# loop over the fields in the rules
130121
for subfield_rules in subfield_rules.fields.values():
131122
for subfield_rule in subfield_rules.rules.values():
132-
result = self.check_rule(field, subfield_rule) and result
123+
self.check_rule(field, subfield_rule)
133124

134125
# Resolve ID and references
135126
if not field.parent:
136127
self.id_manager.resolve_unicity(self.timestamp)
137128
self.id_manager.resolve_references(self.timestamp)
138-
return result
129+
return True
139130

140131

141132
@rule_implementation

Diff for: rules2yml.py

+29-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,18 @@ def command_line_arguments():
2323
required=False,
2424
type=str,
2525
)
26+
parser.add_argument(
27+
"--full-osi",
28+
"-f",
29+
help="Add is_set rule to all fields that do not contain it already.",
30+
action="store_true",
31+
required=False,
32+
)
2633

2734
return parser.parse_args()
2835

2936

30-
def gen_yml_rules(dir_name="rules"):
37+
def gen_yml_rules(dir_name="rules", full_osi=False):
3138
with open(r"open-simulation-interface/rules.yml") as file:
3239
yaml = YAML(typ="safe")
3340
rules_dict = yaml.load(file)
@@ -161,6 +168,15 @@ def gen_yml_rules(dir_name="rules"):
161168
yml_file.write(
162169
(2 * numMessage) * " " + f"{field}:\n"
163170
)
171+
# If option --full-osi is enabled:
172+
# Check if is_set is already a rule for the current field, if not, add it.
173+
if full_osi and not any(
174+
"is_set" in rule for rule in rules
175+
):
176+
yml_file.write(
177+
(2 * numMessage + 2) * " "
178+
+ f"- is_set:\n"
179+
)
164180

165181
if shiftCounter:
166182
for rule in rules:
@@ -217,11 +233,21 @@ def gen_yml_rules(dir_name="rules"):
217233
(2 * numMessage + 8) * " "
218234
+ f"- {rule_list[2]}: {rule_list[3]}\n"
219235
)
220-
elif "is_globally_unique" in rule_list:
236+
# Standalone rules
237+
elif any(
238+
list_item
239+
in [
240+
"is_globally_unique",
241+
"is_set",
242+
"is_iso_country_code",
243+
]
244+
for list_item in rule_list
245+
):
221246
yml_file.write(
222247
(2 * numMessage + 2) * " "
223248
+ f"-{rule}:\n"
224249
)
250+
# Values or parameters of rules
225251
else:
226252
yml_file.write(
227253
(2 * numMessage + 2) * " "
@@ -235,7 +261,7 @@ def gen_yml_rules(dir_name="rules"):
235261
def main():
236262
# Handling of command line arguments
237263
args = command_line_arguments()
238-
gen_yml_rules(args.dir)
264+
gen_yml_rules(args.dir, args.full_osi)
239265

240266

241267
if __name__ == "__main__":

Diff for: tests/tests_rules/test_is_valid.py

-108
This file was deleted.

0 commit comments

Comments
 (0)