Multiple unions of validators not working


I want o validate a list of instruments. I want to achieve two things:

  1. An instrument can be specified in two different ways.
  2. Each instrument has its own set of custom parameters that are allowed.

The code:

vldt1_str = validators.String(enum=['guitar'])
vldt1_obj = validators.Object(
        'instrument': vldt1_str,
        'tuning': validators.String(enum=['standard', 'C', 'D']),
vldt1 = validators.Union(items=[vldt1_str, vldt1_obj])

vldt2_str = validators.String(enum=['piano'])
vldt2_obj = validators.Object(
        'instrument': vldt2_str,
        'numPedals': validators.Integer(minimum=1, maximum=3),
vldt2 = validators.Union(items=[vldt2_str, vldt2_obj])

class PlayInstruments(types.Type):
    instruments = validators.Array(items=validators.Union([vldt1, vldt2]))

def test(p: PlayInstruments)-> dict:
    print('test handler output: {}'.format(dict(p)))
    return {'message': 'hello'}

routes = [
    Route('/test', method='POST', handler=test),

app = App(routes=routes)

if __name__ == '__main__':
    app.serve('', 8000, debug=True)

A few examples of correct JSON requests look as follows:

{ "instruments": ["guitar", {"instrument": "piano"}] }
{ "instruments": ["guitar", {"instrument": "piano", "numPedals": 2}] }
{ "instruments": ["guitar", "piano"] }
{ "instruments": [{"instrument": "piano", "numPedals": 2}, {"instrument": "piano", "numPedals": 3}, {"instrument": "guitar", "tuning": "C"}] }

The problem is that none of these requests validates. Each and every leads to an exception. Some trailing traceback lines follow:

  File "/home/mkosta/.local/share/virtualenvs/apistar-test-b1c5t0T_/lib/python3.6/site-packages/apistar/", line 136, in validate
  File "/home/mkosta/.local/share/virtualenvs/apistar-test-b1c5t0T_/lib/python3.6/site-packages/apistar/", line 62, in error
    message = self.error_message(code)
  File "/home/mkosta/.local/share/virtualenvs/apistar-test-b1c5t0T_/lib/python3.6/site-packages/apistar/", line 66, in error_message
    return self.errors[code].format(**self.__dict__)
KeyError: 'exact'

What is going on here? What am I doing wrong?


Please ignore the whole complicated example.
The cause of problems here is this issue: