OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import sys | 5 import sys |
6 | 6 |
7 _no_value = object() | 7 _no_value = object() |
8 | 8 |
9 | 9 |
10 def _DefaultErrorHandler(error): | 10 def _DefaultErrorHandler(error): |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 self._exc_info = exc_info | 62 self._exc_info = exc_info |
63 if (self._value is _no_value and | 63 if (self._value is _no_value and |
64 self._callback is None and | 64 self._callback is None and |
65 self._exc_info is None): | 65 self._exc_info is None): |
66 raise ValueError('Must have either a value, error, or callback.') | 66 raise ValueError('Must have either a value, error, or callback.') |
67 | 67 |
68 def Then(self, callback, error_handler=_DefaultErrorHandler): | 68 def Then(self, callback, error_handler=_DefaultErrorHandler): |
69 '''Creates and returns a future that runs |callback| on the value of this | 69 '''Creates and returns a future that runs |callback| on the value of this |
70 future, or runs optional |error_handler| if resolving this future results in | 70 future, or runs optional |error_handler| if resolving this future results in |
71 an exception. | 71 an exception. |
| 72 |
| 73 If |callback| returns a non-Future value then the returned Future will |
| 74 resolve to that value. |
| 75 |
| 76 If |callback| returns a Future then it gets chained to the current Future. |
| 77 This means that the returned Future will resolve to *that* Future's value. |
| 78 This behaviour is transitive. |
| 79 |
| 80 For example, |
| 81 |
| 82 def fortytwo(): |
| 83 return Future(value=42) |
| 84 |
| 85 def inc(x): |
| 86 return x + 1 |
| 87 |
| 88 def inc_future(x): |
| 89 return Future(value=x + 1) |
| 90 |
| 91 fortytwo().Then(inc).Get() ==> 43 |
| 92 fortytwo().Then(inc_future).Get() ==> 43 |
| 93 fortytwo().Then(inc_future).Then(inc_future).Get() ==> 44 |
72 ''' | 94 ''' |
73 def then(): | 95 def then(): |
| 96 val = None |
74 try: | 97 try: |
75 val = self.Get() | 98 val = self.Get() |
76 except Exception as e: | 99 except Exception as e: |
77 return error_handler(e) | 100 val = error_handler(e) |
78 return callback(val) | 101 else: |
| 102 val = callback(val) |
| 103 return val.Get() if isinstance(val, Future) else val |
79 return Future(callback=then) | 104 return Future(callback=then) |
80 | 105 |
81 def Get(self): | 106 def Get(self): |
82 '''Gets the stored value, error, or callback contents. | 107 '''Gets the stored value, error, or callback contents. |
83 ''' | 108 ''' |
84 if self._value is not _no_value: | 109 if self._value is not _no_value: |
85 return self._value | 110 return self._value |
86 if self._exc_info is not None: | 111 if self._exc_info is not None: |
87 self._Raise() | 112 self._Raise() |
88 try: | 113 try: |
89 self._value = self._callback() | 114 self._value = self._callback() |
90 return self._value | 115 return self._value |
91 except: | 116 except: |
92 self._exc_info = sys.exc_info() | 117 self._exc_info = sys.exc_info() |
93 self._Raise() | 118 self._Raise() |
94 | 119 |
95 def _Raise(self): | 120 def _Raise(self): |
96 exc_info = self._exc_info | 121 exc_info = self._exc_info |
97 raise exc_info[0], exc_info[1], exc_info[2] | 122 raise exc_info[0], exc_info[1], exc_info[2] |
OLD | NEW |