Skip to content

exporters/vspec: support per-field datatype for enum allowed values (#8)#191

Open
SoundMatt wants to merge 1 commit into
COVESA:mainfrom
SoundMatt:feat/issue-8-enum-vss-datatype
Open

exporters/vspec: support per-field datatype for enum allowed values (#8)#191
SoundMatt wants to merge 1 commit into
COVESA:mainfrom
SoundMatt:feat/issue-8-enum-vss-datatype

Conversation

@SoundMatt
Copy link
Copy Markdown

Summary

Closes #8.

VSS allows any datatype for allowed: values (e.g. integer-valued
Gear: allowed: [1,2,3]), but GraphQL enums are always String at
the schema level, so when the vspec exporter emits VSS the original
datatype information is lost — src/s2dm/exporters/vspec.py:345
hard-codes "datatype": "string" for any enum-typed field.

Approach

Extend the existing @metadata directive with a new optional
vssDatatype: String argument. The vspec exporter reads it for
enum-typed fields. Default "string" when not specified preserves
existing behaviour for every schema not opting in.

Schema authors

directive @metadata(comment: String, vssType: String, vssDatatype: String)
          on FIELD_DEFINITION | OBJECT

type Vehicle {
  gear: GearLevel @metadata(vssType: "sensor", vssDatatype: "int8")
}

enum GearLevel { _1 _2 _3 _4 _5 }

…produces:

Vehicle.gear:
  datatype: int8
  allowed:
  - _1
  - _2
  - _3
  - _4
  - _5
  type: attribute

Why this approach

The trade-offs I considered before settling on @metadata extension:

  • A separate @datatype directive on the enum type (e.g.
    enum GearLevel @datatype(type: "int8") { ... }) — cleaner
    semantically (the enum itself is typed) but introduces a new
    vocabulary. I went with extending @metadata to keep one
    directive-per-concept and avoid bikeshedding the new directive's
    name and target locations.
  • Per-enum-value annotations — overkill; the datatype is
    uniform across all values of an enum.
  • Naming-convention inference (e.g. all values prefixed with
    _ followed by a digit ⇒ int) — too brittle; works only for
    numeric enums, breaks for ["DIESEL","E10","E5"] style.

The directive-arg approach is the smallest reachable change that
solves the problem without bikeshedding new vocabulary or breaking
any existing schema.

Notes for review

  • Issue Handle datatypes for allowed values #8 closes with "How to handle that?" — this is one
    reasonable answer; happy to revise the directive shape if
    you'd prefer something different.
  • The metadata-reading code in this branch duplicates the scalar
    branch's logic (vspec.py:291–305). Extracting a shared helper
    would be cleaner; left untouched here to keep the diff scoped
    to issue Handle datatypes for allowed values #8.
  • The other TODO at line 349 ("Get this from the @metadata directive" for the type: field) is the same shape of
    duplication and would benefit from the same refactor; not
    addressing in this PR.
  • The existing test_export_vspec end-to-end test still passes
    (the new code is a no-op without vssDatatype). Happy to add a
    focused unit test asserting the new behaviour if you can point
    me at the right test fixture pattern.

…OVESA#8)

Issue COVESA#8 raised that VSS allows any datatype for `allowed:` values
(e.g. integer values for `Gear: allowed: [1, 2, 3]`) but GraphQL
represents enum values as strings, so when the GraphQL exporter
emits VSS the datatype information is lost — `vspec.py` line 345
hard-codes `"datatype": "string"`.

Extend the existing `@metadata` directive with a new optional
`vssDatatype` argument and have the vspec exporter read it from the
field's @metadata directive when handling enum-typed fields. Default
to "string" when not specified, preserving existing behaviour.

Schema authors can then opt in:

  directive @metadata(comment: String, vssType: String,
                      vssDatatype: String)
            on FIELD_DEFINITION | OBJECT

  type Vehicle {
    gear: GearLevel @metadata(vssType: "sensor", vssDatatype: "int8")
  }

  enum GearLevel { _1 _2 _3 _4 _5 }

…and the vspec exporter produces:

  Vehicle.gear:
    datatype: int8
    allowed:
    - _1
    - _2
    - _3
    - _4
    - _5
    type: attribute

Notes for review:

- Issue COVESA#8 closes with "How to handle that?" — this is one
  reasonable answer; happy to revise the directive shape if you'd
  prefer a different design (separate @datatype directive on the
  enum type itself, per-enum-value annotations, derive from value
  naming convention, etc.).
- The metadata-reading code in this branch duplicates the logic
  used in the scalar-field branch (lines 291–305). Extracting a
  shared helper would be cleaner; left untouched here to keep the
  diff scoped to issue COVESA#8.
- The other TODO at line 349 ("Get this from the @metadata
  directive" for the `type:` field) is the same shape of
  duplication and would benefit from the same refactor; not
  addressing in this PR.
- Tests: the existing `test_export_vspec` end-to-end test still
  passes (the new code is a no-op without `vssDatatype`). Happy
  to add a focused unit test asserting the new behaviour if
  maintainers point me at the right test fixture.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
@SoundMatt
Copy link
Copy Markdown
Author

FYI — opened #192 as a small follow-up that stacks on this branch (extracts the metadata-reading into a helper and closes the line 349 TODO that we discussed in the review). Happy to merge it into this branch first if you'd prefer one combined PR — just let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle datatypes for allowed values

1 participant