adamcharnock / lightbus

RPC & event framework for Python
https://lightbus.org
Apache License 2.0
199 stars 22 forks source link

Errors when using `Dict`s where the keys are `Enum`s #17

Open adamcharnock opened 4 years ago

adamcharnock commented 4 years ago

For example:

class MyApi(lightbus.Api):
    stock_levels_recalculated = lightbus.Event(parameters=[
        lightbus.Parameter("stock_levels", Dict[PumpKind, int], default=PumpKind.V1)
    ])

    def get_stocked_serials(self, pump_kind: PumpKind = PumpKind.V1) -> List[str]:
        pass

Firing an event with a Dict indexed by PumpKind enums

 lightbus.client                | ERROR: '<' not supported between instances of 'PumpKind' and 'PumpKind' (client:235)
Traceback (most recent call last):
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client.py", line 233, in _close_async_inner
    await cancel(task)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 95, in cancel
    raise ex
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 71, in cancel
    await task
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 120, in exception_handling_context
    yield
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 107, in check_for_exception
    fut.result()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 179, in call_every
    await run_user_provided_callable(callback, args=[], kwargs={}, bus_client=bus_client)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 160, in run_user_provided_callable
    return await future
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 158, in <lambda>
    executor=None, func=lambda: callable(*args, **kwargs)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/bus.py", line 73, in recalculate
    local_apis.recalculate_stock_levels()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/core/apis.py", line 61, in recalculate_stock_levels
    bus.production.statistics.stock_levels_recalculated.fire(stock_levels=levels)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/path.py", line 117, in fire
    timeout=self.client.config.api(self.api_name).event_fire_timeout,
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 47, in block
    raise e
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/utilities/async_tools.py", line 44, in block
    val = loop.run_until_complete(asyncio.wait_for(coroutine, timeout=timeout, loop=loop))
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
    return future.result()
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/asyncio/tasks.py", line 442, in wait_for
    return fut.result()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/path.py", line 111, in fire_async
    api_name=self.api_name, name=self.name, kwargs=kwargs, options=bus_options
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client_worker.py", line 117, in wrapper
    raise result
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client_worker.py", line 346, in perform_calls
    result = await result
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client.py", line 670, in fire_event
    await event_transport.send_event(event_message, options=options, bus_client=self)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/transports/redis.py", line 546, in send_event
    fields=self.serializer(event_message),
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/serializers/by_field.py", line 35, in __call__
    serialized[":{}".format(k)] = self.encoder(v)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/schema/encoder.py", line 7, in json_encode
    return JSONEncoder(indent=indent, sort_keys=sort_keys, **options).encode(obj)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 431, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 353, in _iterencode_dict
    items = sorted(dct.items(), key=lambda kv: kv[0])
TypeError: '<' not supported between instances of 'PumpKind' and 'PumpKind'

Error when creating schema for RPCs with parameters where a Dict is indexed by a PumpKind enum

Traceback (most recent call last):
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/bin/lightbus", line 11, in <module>
    load_entry_point('lightbus', 'console_scripts', 'lightbus')()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/commands/__init__.py", line 27, in lightbus_entry_point
    run_command_from_args()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/commands/__init__.py", line 45, in run_command_from_args
    parsed_args.func(parsed_args, config, plugin_registry, **extra)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/commands/run.py", line 55, in handle
    self._handle(args, config, plugin_registry)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/commands/run.py", line 110, in _handle
    bus.client.run_forever()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client.py", line 253, in run_forever
    self.start_server()
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client_worker.py", line 163, in wrapper
    return fn(*args, **kwargs)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client.py", line 312, in start_server
    block(self._setup_server())
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client_worker.py", line 117, in wrapper
    raise result
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client_worker.py", line 346, in perform_calls
    result = await result
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/client.py", line 328, in _setup_server
    await self.schema.add_api(api)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/schema/schema.py", line 78, in add_api
    await self.schema_transport.store(api.meta.name, schema, ttl_seconds=self.max_age_seconds)
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/transports/redis.py", line 986, in store
    p.set(schema_key, json_encode(schema))
  File "/Users/adam/Projects/futurepump-monorepo/src/python/fp/production/.venv/src/lightbus/lightbus/schema/encoder.py", line 7, in json_encode
    return JSONEncoder(indent=indent, sort_keys=sort_keys, **options).encode(obj)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 431, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  [Previous line repeated 3 more times]
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 438, in _iterencode
    o = _default(o)
  File "/Users/adam/.pyenv/versions/3.7.5/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type PumpKind is not JSON serializable