Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: mojo/public/python/mojo_bindings/promise.py

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """
6 Promise used by the python bindings.
7
8 The API is following the ECMAScript 6 API for promises.
9 """
10
11 import sys
12
13
14 class Promise(object):
15 """The promise object."""
16
17 STATE_PENDING = 0
18 STATE_FULLFILLED = 1
19 STATE_REJECTED = 2
20 STATE_BOUND = 3
21
22 def __init__(self, generator_function):
23 """
24 Constructor.
25
26 Args:
27 generator_function: A function taking 2 arguments: resolve and reject.
28 When |resolve| is called, the promise is fullfilled with the given value.
29 When |reject| is called, the promise is rejected with the given value.
30 A promise can only be resolved or rejected once, all following calls will
31 have no effect.
32 """
33 self._onCatched = []
34 self._onFulfilled = []
35 self._onRejected = []
36 self._state = Promise.STATE_PENDING
37 self._result = None
38 try:
39 generator_function(self._Resolve, self._Reject)
40 except Exception as e:
41 # Adding traceback similarly to python 3.0 (pep-3134)
42 e.__traceback__ = sys.exc_info()[2]
43 self._Reject(e)
44
45 @staticmethod
46 def Resolve(value):
47 """
48 If value is a promise, make a promise that have the same behavior as value,
49 otherwise make a promise that fulfills to value.
50 """
51 if isinstance(value, Promise):
52 return value
53 return Promise(lambda x, y: x(value))
54
55 @staticmethod
56 def Reject(reason):
57 "Make a promise that rejects to reason."""
58 return Promise(lambda x, y: y(reason))
59
60 @staticmethod
61 def All(*iterable):
62 """
63 Make a promise that fulfills when every item in the array fulfills, and
64 rejects if (and when) any item rejects. Each array item is passed to
65 Promise.resolve, so the array can be a mixture of promise-like objects and
66 other objects. The fulfillment value is an array (in order) of fulfillment
67 values. The rejection value is the first rejection value.
68 """
69 def GeneratorFunction(resolve, reject):
70 state = {
71 'rejected': False,
72 'nb_resolved': 0,
73 }
74 promises = [Promise.Resolve(x) for x in iterable]
75 results = [None for x in promises]
76 def OnFullfilled(i):
77 def OnFullfilled(res):
78 if state['rejected']:
79 return
80 results[i] = res
81 state['nb_resolved'] = state['nb_resolved'] + 1
82 if state['nb_resolved'] == len(results):
83 resolve(results)
84 return OnFullfilled
85 def OnRejected(reason):
86 if state['rejected']:
87 return
88 state['rejected'] = True
89 reject(reason)
90
91 for (i, promise) in enumerate(promises):
92 promise.Then(OnFullfilled(i), OnRejected)
93 return Promise(GeneratorFunction)
94
95 @staticmethod
96 def Race(*iterable):
97 """
98 Make a Promise that fulfills as soon as any item fulfills, or rejects as
99 soon as any item rejects, whichever happens first.
100 """
101 def GeneratorFunction(resolve, reject):
102 state = {
103 'ended': False
104 }
105 def OnEvent(callback):
106 def OnEvent(res):
107 if state['ended']:
108 return
109 state['ended'] = True
110 callback(res)
111 return OnEvent
112 for promise in [Promise.Resolve(x) for x in iterable]:
113 promise.Then(OnEvent(resolve), OnEvent(reject))
114 return Promise(GeneratorFunction)
115
116 @property
117 def state(self):
118 if isinstance(self._result, Promise):
119 return self._result.state
120 return self._state
121
122 def Then(self, onFullfilled=None, onRejected=None):
123 """
124 onFulfilled is called when/if this promise resolves. onRejected is called
125 when/if this promise rejects. Both are optional, if either/both are omitted
126 the next onFulfilled/onRejected in the chain is called. Both callbacks have
127 a single parameter, the fulfillment value or rejection reason. |Then|
128 returns a new promise equivalent to the value you return from
129 onFulfilled/onRejected after being passed through Resolve. If an
130 error is thrown in the callback, the returned promise rejects with that
131 error.
132 """
133 if isinstance(self._result, Promise):
134 return self._result.Then(onFullfilled, onRejected)
135 def GeneratorFunction(resolve, reject):
136 if self._state == Promise.STATE_PENDING:
137 self._onFulfilled.append(_Delegate(resolve, reject, onFullfilled))
138 self._onRejected.append(_Delegate(reject, reject, onRejected))
139 if self._state == self.STATE_FULLFILLED:
140 _Delegate(resolve, reject, onFullfilled)(self._result)
141 if self._state == self.STATE_REJECTED:
142 recover = reject
143 if onRejected:
144 recover = resolve
145 _Delegate(recover, reject, onRejected)(self._result)
146 return Promise(GeneratorFunction)
147
148 def Catch(self, onCatched):
149 """Equivalent to |Then(None, onCatched)|"""
150 return self.Then(None, onCatched)
151
152 def _Resolve(self, value):
153 if self.state != Promise.STATE_PENDING:
154 return
155 self._result = value
156 if isinstance(value, Promise):
157 self._state = Promise.STATE_BOUND
158 self._result.Then(_IterateAction(self._onFulfilled),
159 _IterateAction(self._onRejected))
160 return
161 self._state = Promise.STATE_FULLFILLED
162 for f in self._onFulfilled:
163 f(value)
164 self._onFulfilled = None
165 self._onRejected = None
166
167 def _Reject(self, reason):
168 if self.state != Promise.STATE_PENDING:
169 return
170 self._result = reason
171 self._state = Promise.STATE_REJECTED
172 for f in self._onRejected:
173 f(reason)
174 self._onFulfilled = None
175 self._onRejected = None
176
177
178 def _IterateAction(iterable):
179 def _Run(x):
180 for f in iterable:
181 f(x)
182 return _Run
183
184
185 def _Delegate(resolve, reject, action):
186 def _Run(x):
187 try:
188 if action:
189 resolve(action(x))
190 else:
191 resolve(x)
192 except Exception as e:
193 # Adding traceback similarly to python 3.0 (pep-3134)
194 e.__traceback__ = sys.exc_info()[2]
195 reject(e)
196 return _Run
OLDNEW
« no previous file with comments | « mojo/public/python/mojo_bindings/messaging.py ('k') | mojo/public/python/mojo_bindings/reflection.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698