feat(protobuf): generate nested enum for string fields with allowed values - #502
Merged
erikbosch merged 5 commits intoApr 30, 2026
Conversation
sschleemilch
requested changes
Apr 10, 2026
| nodes: tuple[VSSNode], fd: TextIOWrapper, static_uid: bool, add_optional: bool, include_comments: bool | ||
| ): | ||
| # Pass 1: write nested enum definitions for every string field with allowed values. | ||
| for node in nodes: |
Collaborator
There was a problem hiding this comment.
Why do we need to iterate twice?
| for node in nodes: | ||
| if isinstance(node.data, VSSDataDatatype): | ||
| base = node.data.datatype.strip("[]") | ||
| if base == "string" and node.data.allowed: |
Collaborator
There was a problem hiding this comment.
"string" literal will probably never change. Still use the the one from datatypes.Datatypes
…alues When a VSS signal has `datatype: string` and an `allowed` attribute, the protobuf exporter previously emitted a plain `string` field, allowing any value without enforcement. This silently accepted values outside the declared allowed set at the protobuf layer. Fix: `print_messages()` now uses a two-pass approach: - Pass 1: emit a nested `enum <FieldName>Enum` for each string+allowed field, with allowed values assigned indices starting at 0 (satisfying the proto3 zero-value requirement). - Pass 2: emit fields using the enum type instead of `string`. `repeated string[]` fields with `allowed` become `repeated <EnumType>`. Non-string fields and string fields without `allowed` are unchanged. Closes COVESA#493 Co-Authored-By: Claude and aki1770-del <aki1770@gmail.com> Signed-off-by: Akihiko Komada <aki1770@gmail.com>
Co-Authored-By: Claude and aki1770-del <aki1770@gmail.com> Signed-off-by: Akihiko Komada <aki1770@gmail.com>
ruff-format reformatted the multi-line assert to put the condition arguments on their own line instead of wrapping in parentheses. Keeps pre-commit CI green. Co-Authored-By: Claude and aki1770-del <aki1770@gmail.com> Signed-off-by: Akihiko Komada <aki1770@gmail.com>
- Collapse two-pass loop into one: _write_nested_enum is called immediately before the field declaration, removing the redundant pre-iteration. - Replace "string" literal with Datatypes.STRING[0] from datatypes module. - Update expected.proto: enum definitions now appear inline before their respective fields rather than grouped at the top of the message. Co-Authored-By: Claude and aki1770-del <aki1770@gmail.com> Signed-off-by: Akihiko Komada <aki1770@gmail.com>
Move `from vss_tools.datatypes import Datatypes` before `from vss_tools.main import get_trees` — alphabetical within the vss_tools.* group as required by ruff/isort. Co-Authored-By: Claude and aki1770-del <aki1770@gmail.com> Signed-off-by: Akihiko Komada <aki1770@gmail.com>
aki1770-del
force-pushed
the
feat/protobuf-enum-for-allowed-string-493
branch
from
April 11, 2026 10:02
3e69703 to
c151e10
Compare
erikbosch
reviewed
Apr 14, 2026
sschleemilch
approved these changes
Apr 14, 2026
Contributor
Author
|
Thanks @erikbosch — sharp catch on the proto3 zero-default ↔ VSS-default alignment. You're right that ordering To respect the scope of this PR (which you and @sschleemilch have already reviewed), I've filed it as a follow-up: #505 — happy to take it as a separate PR if the direction is confirmed there. AI-assisted — authored with Claude, reviewed by Komada. |
Collaborator
|
MoM:
|
Collaborator
|
MoM:
|
erikbosch
pushed a commit
that referenced
this pull request
Apr 30, 2026
…lowed[0] (#512) * feat(strict): add DEFAULT_MATCHES_FIRST_ALLOWED check for default==allowed[0] Closes #507. Follow-up from #502 (proto3 nested-enum generation for string fields with allowed values). Proto3 uses allowed[0] as the implicit wire-unset default, so VSS default must match allowed[0] for the intent to survive serialization. Canonical VSS pattern per erikbosch + sschleemilch (see #507 comments): allowed: ['UNKNOWN', ...] + default: 'UNKNOWN'. Implementation mirrors existing NAME_STYLE / UNKNOWN_ATTRIBUTE strict checks: - StrictOption.DEFAULT_MATCHES_FIRST_ALLOWED enum member - StrictExceptions.defaults exemption set - load_strict_exceptions dispatch (+ null-options fallback) - VSSNode.get_default_first_allowed_violations tree walk - check_default_first_allowed_violations strict gate in main.py - DefaultFirstAllowedException signal class - aborts CLI choice extended Gated behind --strict or --aborts default-matches-first-allowed; exempt per-FQN via the existing --strict-exceptions file (new option value or null for all-exceptions). No behavior change on default run. Tests: 5 new (1 strict.py enum + dispatch, 4 tree.py violation collector covering clean/mismatch/no-allowed/no-default), plus existing strict.py tests extended with .defaults-set assertions for consistency. 132/132 pass on tests/ (pre-existing test_binary failure unrelated). Chain A: #502 -> #507. Signed-off-by: Akihiko Komada <aki1770@gmail.com> * fix(strict): skip array datatypes in default-matches-first-allowed + ruff-format Array datatypes (`string[]` etc.) don't have a proto3 nested-enum analog for the default-equals-allowed[0] rule — per-element allowed-membership is already enforced at the pydantic VSSDataDatatype layer. Previous implementation incorrectly flagged `tests/vspec/test_datatypes_pattern/test_pattern_ok.vspec` (A.Colors: string[] with allowed=[white,...,blue] and default=[white,green,red]) as a violation because default (a list) != allowed[0] (a scalar). Adds early-continue on `node.data.datatype.endswith("[]")` and a regression test covering the exact fixture shape. Also applies ruff-format on main.py and cli_options.py to satisfy the pre-commit ruff-format hook (whitespace-only changes). Signed-off-by: Akihiko Komada <aki1770@gmail.com> * fix(strict): match upstream ruff 0.5.7 import style Signed-off-by: Akihiko Komada <aki1770@gmail.com> --------- Signed-off-by: Akihiko Komada <aki1770@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #493
Problem
When a VSS signal has
datatype: stringand anallowedattribute, the protobuf exporter emits a plainstringfield. This silently accepts any value at the protobuf layer — the constraint declared in the VSS spec is invisible to protobuf consumers.Fix
print_messages()now uses a two-pass approach insrc/vss_tools/exporters/protobuf.py:string+allowedfield, emit a nestedenum <FieldName>Enumwith allowed values assigned indices starting at 0 (satisfying the proto3 zero-value requirement).string.repeated string[]fields withallowedbecomerepeated <EnumType>. String fields withoutallowedand all non-string fields are unchanged.Note on proto3 zero-value semantics: proto3 uses the first enum entry as the default for unset fields. This implementation assigns index 0 to the first entry in the VSS
allowedlist. For signals that follow the convention of listingUNKNOWNfirst (e.g.,Vehicle.Exterior.RoadSurfaceCondition), this aligns naturally. For signals without a natural "unset" first value, the first allowed entry becomes the proto default. Happy to discuss if a different index assignment strategy is preferred.Changes
src/vss_tools/exporters/protobuf.py_enum_type_name(),_write_nested_enum(), two-pass logic inprint_messages()tests/vspec/test_protobuf_enum_allowed/tests/vspec/test_protobuf_comments/expected_*.protoStringWithAllowedfixtureTests
All 13 protobuf-related tests pass, including the two existing
test_protobuf_commentsparametrized cases (no-comments / with-comments) which already contained astring+allowedfield in their fixture.AI-assisted — authored with Claude, reviewed by Komada.