Summary
In accelerator.schema.json several classes appear twice in a oneOf union: once directly and once inside a nested union of their base class. JSON Schema oneOf requires exactly one match, so every such entry is rejected with "is valid under each of …" / "Matches multiple schemas when only one must validate" (yaml-language-server), even though it is correct.
Affected:
properties.devices.items.oneOf: HCorrector, VCorrector, Quadrupole, SkewQuad, Sextupole, Octupole, SkewSext, SkewOctu, CombinedFunctionMagnet are listed directly and inside the nested MagnetConfigurationSchema oneOf (item 4); same pattern for MeasurementToolConfigurationSchema / TuningToolConfigurationSchema (items 21, 26).
StaticCatalogEntry.properties.device.oneOf: tango.pyaml.attribute_read_only.AttributeReadOnly and the pyaml_cs_oa.epics* classes appear directly and in a nested oneOf.
Reproduction
import json, jsonschema
s = json.load(open("schemas/accelerator.schema.json"))
branches = s["properties"]["devices"]["anyOf"][0]["items"]["oneOf"]
q = {"class": "pyaml.magnet.quadrupole.Quadrupole", "name": "Q1",
"model": {"class": "pyaml.magnet.linear_model.LinearMagnetModel", "unit": "1/m", "hardware_unit": "A"}}
print(sum(jsonschema.Draft202012Validator(b).is_valid(q) for b in branches)) # 2 -> oneOf fails
On a real configuration (SOLEIL storage ring, 569 devices / 698 catalog entries): 429 devices and 257 catalog entries are rejected for this reason only; with oneOf rewritten to anyOf the configuration validates with 0 errors.
Cause
model_schema builds the union of all registry entries that are subclasses of the model (issubclass(schema_cls, model_cls)), including intermediate base classes (MagnetConfigurationSchema, …) whose own schema is again expanded into a union of the same leaves — so leaves are emitted twice. The TODO: get the schemas to work when using oneOf instead comment at generator.py:232 seems related.
Expected
Either flatten unions (emit each concrete class once, skip intermediate bases that expand to a union), or emit anyOf — as the docstring of model_schema (lines 184-187) actually recommends.
Summary
In
accelerator.schema.jsonseveral classes appear twice in aoneOfunion: once directly and once inside a nested union of their base class. JSON SchemaoneOfrequires exactly one match, so every such entry is rejected with "is valid under each of …" / "Matches multiple schemas when only one must validate" (yaml-language-server), even though it is correct.Affected:
properties.devices.items.oneOf:HCorrector,VCorrector,Quadrupole,SkewQuad,Sextupole,Octupole,SkewSext,SkewOctu,CombinedFunctionMagnetare listed directly and inside the nestedMagnetConfigurationSchemaoneOf(item 4); same pattern forMeasurementToolConfigurationSchema/TuningToolConfigurationSchema(items 21, 26).StaticCatalogEntry.properties.device.oneOf:tango.pyaml.attribute_read_only.AttributeReadOnlyand thepyaml_cs_oa.epics*classes appear directly and in a nestedoneOf.Reproduction
On a real configuration (SOLEIL storage ring, 569 devices / 698 catalog entries): 429 devices and 257 catalog entries are rejected for this reason only; with
oneOfrewritten toanyOfthe configuration validates with 0 errors.Cause
model_schemabuilds the union of all registry entries that are subclasses of the model (issubclass(schema_cls, model_cls)), including intermediate base classes (MagnetConfigurationSchema, …) whose own schema is again expanded into a union of the same leaves — so leaves are emitted twice. TheTODO: get the schemas to work when using oneOf insteadcomment at generator.py:232 seems related.Expected
Either flatten unions (emit each concrete class once, skip intermediate bases that expand to a union), or emit
anyOf— as the docstring ofmodel_schema(lines 184-187) actually recommends.