I ran into this problem too so posting a solution for future reference. One way to accomplish this is to create a subclass with some custom logic.
class AtLeastOneSchema(Schema):
one_required = {'name', 'name_id'}
def validate(self, data, **kwargs):
val_schema = Schema(
self.schema,
self._error,
self._ignore_extra_keys,
self._name,
self._description,
self.as_reference,
)
# This part validates your schema like normal
# required to avoid recursive calls to this exact
# validate method
rv = val_schema.validate(data, **kwargs)
# Now to the custom logic to ensure one of the keys exists
e = self._error
found_one = False
for key in data:
if key in self.one_required:
found_one = True
if not found_one:
message = (
f"Missing key from {self.one_required}"
)
raise SchemaError(message, e.format(data) if e else None)
return rv
Now you can create your schema with the new subclass
mydict_schema = AtLeastOneSchema({
Optional('name'): str,
Optional('name_id'): int,
Optional(str): str # so that you can add any other arbitrary data
})
Example usage:
>>> good_data = {'name': "john"}
>>> mydict_schema.validate(good_data)
{'name': 'john'}
>>> bad_data = {"foo": "bar"}
>>> mydict_schema.validate(bad_data)
Traceback (most recent call last):
schema.SchemaError: Missing key from {'name', 'name_id'}