Opened 7 years ago

Last modified 7 years ago

#6292 enhancement new

Add a helper to add a callback that doesn't affect the result of a defered.

Reported by: Tom Prince Owned by: Tom Prince
Priority: normal Milestone:
Component: core Keywords:
Cc: Hynek Schlawack, Glyph Branch: branches/defer-passthru-helper-6292
branch-diff, diff-cov, branch-cov, buildbot
Author: tomprince

Description

Often, when adding callbacks, one wants to call a function, but ignore the result of that function, and propagate the value of the deferred. The following decorator implements that.

def helper(f):
  def cb(*args, *kwargs):
     f(*args, *kwargs)
     return args[0]
  return cb

A few sample usages follow:

def fork(d):
   newD = Deferred()
   d.addBoth(helper(newD.callback))
   return newD

def assertNoResult(self, d):
   result = []
   d.addCallback(helper(result.append))
   self.assertEqual(result, [])

d.addCallback(helper(lambda r: log.msg(format="got %(value)r", value=r)))

Change History (7)

comment:1 Changed 7 years ago by Tom Prince

Note: I don't know what a good name for this function would be.

comment:2 Changed 7 years ago by Hynek Schlawack

Cc: Hynek Schlawack added

comment:3 Changed 7 years ago by Tom Prince

Author: tomprince
Branch: branches/defer-passthru-helper-6292

(In [37060]) Branching to defer-passthru-helper-6292.

comment:4 Changed 7 years ago by Tom Prince

Keywords: review added

The docstrings could use some improvement, and the deferred howto needs updating still.

comment:5 Changed 7 years ago by Glyph

Keywords: review removed
Owner: set to Tom Prince

I think that the desire to have secret side-effects like this this is a code smell; I don't think that the ticket description is a sufficiently compelling motivation to add this feature at all. I'd rather just close as wontfix.

Even if it is desirable, munging passthru to take on this responsibility seems like a mistake. It's a very simple function right now, with a fixed argument list and basically no code in it (very easy for e.g. the PyPy JIT to optimize the heck out of it). Adding variadic args and other weirdness seems bad to me; bad for clarity (now if you invoke passthru with too many args instead of a tuple by accident, you will start calling random bits of its argument list) and maybe bad for performance too.

In my opinion, the fact that you're having a hard time coming up for a name for this thing is an indication that it's a bad thing to have. Think about some language describing the effect you're trying to achieve.

comment:6 Changed 7 years ago by Glyph

Cc: Glyph added

comment:7 Changed 7 years ago by Tom Prince

Another example of where something like this would be useful ( context):

d = file.receive()
d.addCallback(cbConsumer)
d.addCallback(lambda ignored: file.close())
d.addCallbacks(cbSent, ebSent)

Since the file.close probably wants to be done in the error case as well, but propagate the error.

That is, for code that would be in the finally block of synchronous code.

Note: See TracTickets for help on using tickets.