[Twisted-Python] Problems with inlineCallback, Deferred, yield and Python 3 in buildbot
Craig Rodrigues
rodrigc at crodrigues.org
Tue Jan 24 13:48:07 MST 2017
On Mon, Jan 23, 2017 at 5:10 PM, Jean-Paul Calderone <
exarkun at twistedmatrix.com> wrote:
> On Mon, Jan 23, 2017 at 7:08 PM, Craig Rodrigues <rodrigc at crodrigues.org>
> wrote:
>
>>
>>
>>
>> I did some more debugging. The callstack is quite deep. :/
>> I used this command to trigger the error:
>>
>> trial buildbot.test.unit.test_process_buildrequestdistributor.Tes
>> tMaybeStartBuilds.test_slow_db
>>
>> I found in this function in buildbot's BuildRequestsEndpoint.get()
>> function ( https://github.com/buildbot/buildbot/blob/master/master/buil
>> dbot/data/buildrequests.py#L146 ) there is this line:
>>
>>
>>
>> * defer.returnValue( [(yield self.db2data(br)) for br
>> in buildrequests])*
>> On Python 2, this line returns:
>> an object list
>> each list entry is a dictionary of name/value pairs that looks like:
>>
>> [{'buildrequestid': 10, 'complete': False, 'waited_for': False,
>> 'claimed_at': None, 'results': -1, 'claimed': False, 'buildsetid': 11,
>> 'complete_at': None, 'submitted_at': datetime.datetime(1970, 1, 2, 12, 6,
>> 40, tzinfo=tzutc()), 'builderid': 77, 'claimed_by_masterid': None,
>> 'priority': 0}, {'buildrequestid': 11, 'complete': False, 'waited_for':
>> False, 'claimed_at': None, 'results': -1, 'claimed': False, 'buildsetid':
>> 11, 'complete_at': None, 'submitted_at': datetime.datetime(1970, 1, 2, 13,
>> 30, tzinfo=tzutc()), 'builderid': 77, 'claimed_by_masterid': None,
>> 'priority': 0}]
>>
>> On Python 3, this returns:
>> an object <generator object BuildRequestsEndpoint.get.<loc
>> als>.<listcomp>
>> of type <class 'generator'>
>>
>>
> Yep.
>
> On Python 2, [(yield self.db2data(br)) for br in buildrequests] is a list
> comprehension. It will have len(buildrequests) elements and each will be
> the value sent back in to the generator via the yield expression.
>
> On Python 3, the same expression is a list of one element which is a
> generator expression.
>
> This form is much clearer, I think, and behaves as intended on both
> versions of Python:
>
> results = []
> for br in buildrequests:
> results.append((yield self.db2data(br)))
> defer.returnValue(results)
>
>
>
Wow, thanks! That fixed it. I submitted those fixes upstream to buildbot.
I'm not so familiar with generator expressions and Deferred's so have been
playing
around with things to try to understand.
I went back to the problem code, and changed:
* defer.returnValue( [(yield self.db2data(br)) for br in
buildrequests])*
to:
* defer.returnValue(*
* list([**(yield self.db2data(br)) for br in buildrequests])*
and ran the code under Python 3 and got a return value of:
[ Deferred ]
instead of:
[ {......} ]
where the Deferred.results value was the dictionary.
How does Python 2 directly go to returning the dictionary out of the
Deferred,
while Python 3 returns the Deferred inside the list? self.db2data()
returns a Deferred.
Thanks.
--
Craig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20170124/ccb10c1a/attachment-0002.html>
More information about the Twisted-Python
mailing list