chaosguru
chaosguru

Reputation: 1983

Python Twisted Defer returnValue incompatible with dict

I am using twisted.internet.defer extensively in my package , I have encountered a problem which I am unable to solve after spending 2 days on it. Below is my problem scenario.

# all imports done and correct
class infrastructure: # line 1

  @inlineCallbacks
  def dict_service(self):
    client = MyClient()
    services = yield client.listServices() # line 5
    ret = (dict(service.name, [cont.container_id for cont in service.instances]) for service in dockerServices)
    returnValue(ret) # line 7

I am calling my client which returns me list of Services. listServices() return type is twisted.internet.defer.ReturnValue .

class myinterface:
   # has infrastructure

  def init:
     data = dict(
        container_services=self._infrastructure.dict_service(),
        )

when executing this I get below error which I am unable to comprehend. can someone please help.

raise TypeError(repr(o) + \" is not JSON serializable\")\nexceptions.TypeError: <DeferredWithContext at 0x4bfbb48 current result: <twisted.python.failure.Failure <type 'exceptions.NameError'>>> is not JSON serializable\n"

Is it because that wrapping dict with returnValue creating problem?

Upvotes: 0

Views: 1188

Answers (1)

Jean-Paul Calderone
Jean-Paul Calderone

Reputation: 48335

There's no problem using returnValue with a dict instance:

$ python -m twisted.conch.stdio
>>> from __future__ import print_function
>>> from twisted.internet.defer import inlineCallbacks, returnValue
>>> @inlineCallbacks
... def f():
...     d = yield {"foo": "bar"} # Yield *something* or it's not a generator
...     returnValue(d)
... 
>>> f().addCallback(print)
{'foo': 'bar'}
<Deferred at 0x7f84c51847a0 current result: None>

The error you reported:

raise TypeError(repr(o) + \" is not JSON serializable\")\nexceptions.TypeError: <DeferredWithContext at 0x4bfbb48 current result: <twisted.python.failure.Failure <type 'exceptions.NameError'>>> is not JSON serializable\n"

Makes it appear as though you have some code that triggers a NameError. This seems to happen in a Deferred callback (or otherwise makes its way into a Deferred) and gets wrapped in a Failure:

<twisted.python.failure.Failure <type 'exceptions.NameError'>>

That leaves:

raise TypeError(repr(o) + \" is not JSON serializable\")\nexceptions.TypeError: <DeferredWithContext at 0x4bfbb48 current result: ...> is not JSON serializable\n"

I don't know what DeferredWithContext is. I'm guessing it's a subclass of Deferred with some additional behavior. It'd be nice if you could link to the library that provides this (it seems like a bad idea to me but I'd like to understand more).

If that's so, then the error is talking about a DeferredWithContext instance that has the above-described Failure as its result:

<DeferredWithContext at 0x4bfbb48 current result: ...>

That leaves:

raise TypeError(repr(o) + \" is not JSON serializable\")\nexceptions.TypeError: ... is not JSON serializable\n"

This seems to come from the json module, either the dump or dumps function. This is claiming something that is not JSON serializable was passed in. DeferredWithContext is almost certainly not JSON serializable, so that explains the problem.

This would result from something like:

json.dumps(function_that_returns_deferred())

which should instead be:

function_that_returns_deferred().addCallback(json.dumps)

Upvotes: 1

Related Questions