title: How do I write this as a context manager?
body: <p>The race-condition-free way of updating a variable in redis is:</p>
  
  <pre><code>r = redis.Redis()
  with r.pipeline() as p:
      while 1:
          try:
              p.watch(KEY)
              val = p.get(KEY)
              newval = int(val) + 42
              p.multi()
              p.set(KEY, newval)
              p.execute()  # raises WatchError if anyone else changed KEY
              break
          except redis.WatchError:
              continue  # retry
  </code></pre>
  
  <p>this is significantly more complex than the straight forward version (which contains a race-condition):</p>
  
  <pre><code>r = redis.Redis()
  val = r.get(KEY)
  newval = int(val) + 42
  r.set(KEY, newval) 
  </code></pre>
  
  <p>so I thought a context manager would make this easier to work with, however, I'm having problems...</p>
  
  <p>My initial idea was</p>
  
  <pre><code>with update(KEY) as val:
      newval = val + 42
      somehow return newval to the contextmanager...?
  </code></pre>
  
  <p>there wasn't an obvious way to do the last line, so I tried::</p>
  
  <pre><code>@contextmanager
  def update(key, cn=None):
      """Usage::
  
              with update(KEY) as (p, val):
                  newval = int(val) + 42
                  p.set(KEY, newval)
  
      """
      r = cn or redis.Redis()
      with r.pipeline() as p:
          while 1:
              try:
                  p.watch(key)  # --&gt; immediate mode
                  val = p.get(key)
                  p.multi()  # --&gt; back to buffered mode
                  yield (p, val)
                  p.execute()  # raises WatchError if anyone has changed `key`
                  break  # success, break out of while loop
              except redis.WatchError:
                  pass  # someone else got there before us, retry.
  </code></pre>
  
  <p>which works great as long as I don't catch a <code>WatchError</code>, then I get </p>
  
  <pre><code>  File "c:\python27\Lib\contextlib.py", line 28, in __exit__
      raise RuntimeError("generator didn't stop")
  RuntimeError: generator didn't stop
  </code></pre>
  
  <p>what am I doing wrong?</p>