1 from __future__ import division
8 from twisted.internet import defer, reactor
9 from twisted.python import failure
10 from twisted.web import resource, server
12 class DeferredResource(resource.Resource):
13 def render(self, request):
15 if request._disconnected:
21 def finish_error(fail):
22 if request._disconnected:
24 request.setResponseCode(500) # won't do anything if already written to
25 request.write('---ERROR---')
29 defer.maybeDeferred(resource.Resource.render, self, request).addCallbacks(finish, finish_error)
30 return server.NOT_DONE_YET
35 self.one_time_observers = {}
36 self.id_generator = itertools.count()
38 def watch(self, func):
39 id = self.id_generator.next()
40 self.observers[id] = func
42 def unwatch(self, id):
43 self.observers.pop(id)
45 def watch_one_time(self, func):
46 id = self.id_generator.next()
47 self.one_time_observers[id] = func
49 def unwatch_one_time(self, id):
50 self.one_time_observers.pop(id)
52 def happened(self, event=None):
53 for func in self.observers.itervalues():
56 one_time_observers = self.one_time_observers
57 self.one_time_observers = {}
58 for func in one_time_observers.itervalues():
61 def get_deferred(self):
63 self.watch_one_time(df.callback)
66 class Variable(object):
67 def __init__(self, value):
69 self.changed = Event()
72 if value == self.value:
76 self.changed.happened(value)
78 def get_not_none(self):
79 if self.value is not None:
80 return defer.succeed(self.value)
83 self.changed.watch_one_time(df.callback)
88 reactor.callLater(t, d.callback, None)
92 # don't really need a complex algorithm here
94 left = (len(y) - 1)//2
96 return (y[left] + y[right])/2
98 class StringBuffer(object):
99 'Buffer manager with great worst-case behavior'
101 def __init__(self, data=''):
102 self.buf = collections.deque([data])
103 self.buf_len = len(data)
107 return self.buf_len - self.pos
110 self.buf.append(data)
111 self.buf_len += len(data)
113 def get(self, wants):
114 if self.buf_len - self.pos < wants:
115 raise IndexError('not enough data')
118 seg = self.buf[0][self.pos:self.pos+wants]
120 while self.buf and self.pos >= len(self.buf[0]):
121 x = self.buf.popleft()
122 self.buf_len -= len(x)
129 def _DataChunker(receiver):
130 wants = receiver.next()
134 if len(buf) >= wants:
135 wants = receiver.send(buf.get(wants))
138 def DataChunker(receiver):
140 Produces a function that accepts data that is input into a generator
141 (receiver) in response to the receiver yielding the size of data to wait on
143 x = _DataChunker(receiver)
147 class ReplyMatcher(object):
148 def __init__(self, func, timeout=5):
150 self.timeout = timeout
153 def __call__(self, id):
156 uniq = random.randrange(2**256)
157 df = defer.Deferred()
159 df, timer = self.map[id].pop(uniq)
160 df.errback(failure.Failure(defer.TimeoutError()))
163 self.map.setdefault(id, {})[uniq] = (df, reactor.callLater(self.timeout, timeout))
167 traceback.print_exc()
169 def got_response(self, id, resp):
170 if id not in self.map:
172 for df, timer in self.map.pop(id).itervalues():
176 class GenericDeferrer(object):
177 def __init__(self, max_id, func, timeout=5):
180 self.timeout = timeout
183 def __call__(self, *args, **kwargs):
185 id = random.randrange(self.max_id)
186 if id not in self.map:
188 df = defer.Deferred()
191 df.errback(failure.Failure(defer.TimeoutError()))
192 timer = reactor.callLater(self.timeout, timeout)
193 self.func(id, *args, **kwargs)
194 self.map[id] = df, timer
197 def got_response(self, id, resp):
198 if id not in self.map:
200 df, timer = self.map.pop(id)
204 class NotNowError(Exception):
207 class DeferredCacher(object):
208 def __init__(self, func, backing=None):
213 self.backing = backing
216 @defer.inlineCallbacks
217 def __call__(self, key):
218 if key in self.waiting:
219 yield self.waiting[key]
221 if key in self.backing:
222 defer.returnValue(self.backing[key])
224 self.waiting[key] = defer.Deferred()
226 value = yield self.func(key)
228 self.waiting.pop(key).callback(None)
230 self.backing[key] = value
231 defer.returnValue(value)
233 def call_now(self, key):
234 if key in self.waiting:
237 if key in self.backing:
238 return self.backing[key]
240 self.waiting[key] = defer.Deferred()
242 self.backing[key] = value
243 self.waiting.pop(key).callback(None)
245 self.waiting.pop(key).callback(None)
246 fail.printTraceback()
247 self.func(key).addCallback(cb).addErrback(eb)
250 def pubkey_to_address(pubkey, testnet):
251 if len(pubkey) != 65:
252 raise ValueError('invalid pubkey')
253 version = 111 if testnet else 0
254 key_hash = chr(version) + hashlib.new('ripemd160', hashlib.sha256(pubkey).digest()).digest()
255 checksum = hashlib.sha256(hashlib.sha256(key_hash).digest()).digest()[:4]
256 return base58_encode(key_hash + checksum)
258 def base58_encode(data):
259 return '1'*(len(data) - len(data.lstrip(chr(0)))) + natural_to_string(string_to_natural(data), '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')
261 def natural_to_string(n, alphabet=None, min_width=1):
266 return s.decode('hex').rjust(min_width, '\x00')
269 n, x = divmod(n, len(alphabet))
270 res.append(alphabet[x])
272 return ''.join(res).rjust(min_width, '\x00')
274 def string_to_natural(s, alphabet=None):
278 if not s or (s != alphabet[0] and s.startswith(alphabet[0])):
280 return sum(alphabet.index(char) * len(alphabet)**i for i, char in enumerate(reversed(s)))
283 class DictWrapper(object):
284 def encode_key(self, key):
286 def decode_key(self, encoded_key):
288 def encode_value(self, value):
290 def decode_value(self, encoded_value):
293 def __init__(self, inner):
297 return len(self.inner)
299 def __contains__(self, key):
300 return self.encode_key(key) in self.inner
302 def __getitem__(self, key):
303 return self.decode_value(self.inner[self.encode_key(key)])
304 def __setitem__(self, key, value):
305 self.inner[self.encode_key(key)] = self.encode_value(value)
306 def __delitem__(self, key):
307 del self.inner[self.encode_key(key)]
310 for encoded_key in self.inner:
311 yield self.decode_key(encoded_key)
315 return list(self.iterkeys())
318 for encoded_value in self.inner.itervalues():
319 yield self.decode_value(encoded_value)
321 return list(self.itervalue())
324 for key, value in self.inner.iteritems():
325 yield self.decode_key(key), self.decode_value(value)
327 return list(self.iteritems())
329 def update_dict(d, **replace):
331 for k, v in replace.iteritems():