def test_done_all(): counter = [0] def inc(_): counter[0] += 1 def dec(_): counter[0] -= 1 p = Promise() p.done_all() p.done_all((inc, dec)) p.done_all([ (inc, dec), (inc, dec), {'success': inc, 'failure': dec}, ]) p.fulfill(4) assert_equals(counter[0], 4) p = Promise() p.done_all() p.done_all((inc, dec)) p.done_all([ (inc, dec), {'success': inc, 'failure': dec}, ]) p.reject(Exception()) assert_equals(counter[0], 1)
def test_3_2_6_3_if_fulfilled(): """ Testing return of pending promises to make sure they are properly chained. This covers the case where the root promise is fulfilled before the chaining is defined. """ p1 = Promise() p1.fulfill(10) pending = Promise() pending.fulfill(5) pf = p1.then(lambda r: pending) assert pending.isFulfilled assert_equals(5, pending.value) assert pf.isFulfilled assert_equals(5, pf.value) p2 = Promise() p2.fulfill(10) bad = Promise() bad.reject(Exception("Error")) pr = p2.then(lambda r: bad) assert_exception(bad.reason, Exception, "Error") assert pr.isRejected assert_exception(pr.reason, Exception, "Error")
def test_3_2_6_3_if_fulfilled(): """ Testing return of pending promises to make sure they are properly chained. This covers the case where the root promise is fulfilled before the chaining is defined. """ p1 = Promise() p1.fulfill(10) pending = Promise() pending.fulfill(5) pf = p1.then(lambda r: pending) assert pending.isFulfilled() assert_equals(5, pending.value) assert pf.isFulfilled() assert_equals(5, pf.value) p2 = Promise() p2.fulfill(10) bad = Promise() bad.reject("Error") pr = p2.then(lambda r: bad) assert bad.isRejected() assert_equals("Error", bad.reason) assert pr.isRejected() assert_equals("Error", pr.reason)
def handle_request(self, request): request_indication = map_request_to_request_indication(request) #TODO: "check authorization of requestingEntity based on default access rights" p = Promise() if request_indication.method != "retrieve": return p.reject(SCLMethodNotAllowed(request_indication.method)) path = urlparse(request_indication.path).path channel_id = path[len(PREFIX) + 1:] try: notification, content_type = self.queues[channel_id].popleft() except KeyError: self.logger.info("Polling on unknown channel: %s", channel_id) return p.reject(SCLNotFound(path)) except IndexError: #TODO: handle timeouts self.waiting[channel_id].append(p) else: response_confirmation = RetrieveResponseConfirmation( notification, content_type) response = map_response_confirmation_to_response( request, response_confirmation) p.fulfill(response) self.logger.debug("Returning channel promise: %s", p.isPending()) return p
def test_then_all(): p = Promise() handlers = [ ((lambda x: x * x), (lambda r: 1)), {'success': (lambda x: x + x), 'failure': (lambda r: 2)}, ] results = p.then_all() + p.then_all(((lambda x: x * x), (lambda r: 1))) + p.then_all(handlers) p.fulfill(4) assert_equals(results[0].value, 16) assert_equals(results[1].value, 16) assert_equals(results[2].value, 8) p = Promise() handlers = [ ((lambda x: x * x), (lambda r: 1)), {'success': (lambda x: x + x), 'failure': (lambda r: 2)}, ] results = p.then_all() + p.then_all(((lambda x: x * x), (lambda r: 1))) + p.then_all(handlers) p.reject(Exception()) assert_equals(results[0].value, 1) assert_equals(results[1].value, 1) assert_equals(results[2].value, 2)
def test_3_2_6_3_when_fulfilled(): """ Testing return of pending promises to make sure they are properly chained. This covers the case where the root promise is fulfilled after the chaining is defined. """ p1 = Promise() pending = Promise() pf = p1.then(lambda r: pending) assert pending.isPending assert pf.isPending p1.fulfill(10) pending.fulfill(5) assert pending.isFulfilled assert_equals(5, pending.value) assert pf.isFulfilled assert_equals(5, pf.value) p2 = Promise() bad = Promise() pr = p2.then(lambda r: bad) assert bad.isPending assert pr.isPending p2.fulfill(10) bad.reject(Exception("Error")) assert bad.isRejected assert_exception(bad.reason, Exception, "Error") assert pr.isRejected assert_exception(pr.reason, Exception, "Error")
def testNonFunction(nonFunction): def foo(k, r): results[k] = r p1 = Promise() p2 = p1.then(nonFunction, lambda r: foo(str(nonFunction), r)) p1.reject(Exception("Error: " + str(nonFunction)))
def process_connectivity_request(self, req_category, requested_ssid=None): self.logger.info( "processing connectivity request with request category " + str(req_category)) p = Promise() if requested_ssid: ssid = requested_ssid else: #get the AN info for which the req_category can be served ssid = self.wifi_manager.get_ssid_for_req_category(req_category) self.logger.info("found suitable network with ssid %s", ssid) if ssid is not None: self.logger.info( "found suitable network with ssid %s, current ssid %s", ssid, self.wifi_manager.current_ssid) def conn_callback(dict_reply): if dict_reply is None: self.logger.info("invalid conn_callback dict_reply") #p.reject() self.logger.info( "connectivity callback for trying to connect on " + ssid + " has status " + dict_reply["status"]) if dict_reply["ssid"].startswith('"'): # Unquote dict_reply["ssid"] = dict_reply["ssid"][1:-1] if dict_reply["status"] != "CONNECTED" or dict_reply[ "ssid"] != ssid: self.logger.info( "status is not CONNECTED or current ssid not %s rejecting... (%s instead)" % (ssid, dict_reply["ssid"])) #p.reject() else: channel_tuple = (ssid, req_category) self.logger.debug( "Handover is done, fulfilling with ssid %s" % ssid) p.fulfill(channel_tuple) self.wifi_manager.removeConnectionAlert(conn_callback) if ssid == self.wifi_manager.current_ssid: self.logger.info( "no need to handover, the current ssid is good enough") channel_tuple = (ssid, req_category) p.fulfill(channel_tuple) else: self.wifi_manager.addConnectionAlert(conn_callback) self.wifi_manager.connectToNetwork(ssid, conn_callback) self.logger.info("trying to connect on network with ssid %s", ssid) else: p.reject("no WiFi for request category " + req_category + " available") return p
def test_exceptions(): def throws(v): assert False p1 = Promise() p1.addCallback(throws) p1.fulfill(5) p2 = Promise() p2.addErrback(throws) p2.reject("Error")
def test_3_2_6_5_rejected(): """ Handles the case where the arguments to then are values, not functions or promises. """ p1 = Promise() p1.reject(Exception("Error")) p2 = p1.then(None, 5) assert_exception(p1.reason, Exception, "Error") assert p2.isRejected assert_exception(p2.reason, Exception, "Error")
def test_3_2_1(): """ Test that the arguments to 'then' are optional. """ p1 = Promise() p2 = p1.then() p3 = Promise() p4 = p3.then() p1.fulfill(5) p3.reject(Exception("How dare you!"))
def test_3_2_6_5_rejected(): """ Handles the case where the arguments to then are values, not functions or promises. """ p1 = Promise() p1.reject("Error") p2 = p1.then(None, 5) assert_equals("Error", p1.reason) assert p2.isRejected() assert_equals("Error", p2.reason)
def test_3_2_1(): """ Test that the arguments to 'then' are optional. """ p1 = Promise() p2 = p1.then() p3 = Promise() p4 = p3.then() p1.fulfill(5) p3.reject("How dare you!")
def test_3_2_2_3(): """ Make sure fulfilled callback never called if promise is rejected """ cf = Counter() cr = Counter() p1 = Promise() p2 = p1.then(lambda v: cf.tick(), lambda r: cr.tick()) p1.reject(Exception("Error")) assert_equals(0, cf.value()) assert_equals(1, cr.value())
def test_3_2_2_3(): """ Make sure fulfilled callback never called if promise is rejected """ cf = Counter() cr = Counter() p1 = Promise() p2 = p1.then(lambda v: cf.tick(), lambda r: cr.tick()) p1.reject("Error") assert_equals(0, cf.value()) assert_equals(1, cr.value())
def test_exceptions(): def throws(v): assert False p1 = Promise() p1.addCallback(throws) p1.fulfill(5) p2 = Promise() p2.addErrback(throws) p2.reject(Exception()) assert_raises(Exception, p2.get)
def test_3_2_3_1(): """ The second argument to 'then' must be called when a promise is rejected. """ c = Counter() def check(r, c): assert_equals(r, "Error") c.tick() p1 = Promise() p2 = p1.then(None, lambda r: check(r, c)) p1.reject("Error") assert_equals(1, c.value())
def stop(self): p = Promise() if not self.started: p.reject(OpenMTCError("Plugin %s was not started")) else: self.__promise = p try: self._stop() except BaseException as e: self.logger.exception("Failed to stop plugin") self._error(e) return p
def test_3_2_6_1(): """ Promises returned by then must be fulfilled when the promise they are chained from is fulfilled IF the fulfillment value is not a promise. """ p1 = Promise() pf = p1.then(lambda v: v * v) p1.fulfill(5) assert_equals(pf.value, 25) p2 = Promise() pr = p2.then(None, lambda r: 5) p2.reject(Exception("Error")) assert_equals(5, pr.value)
def test_3_2_6_1(): """ Promises returned by then must be fulfilled when the promise they are chained from is fulfilled IF the fulfillment value is not a promise. """ p1 = Promise() pf = p1.then(lambda v: v*v) p1.fulfill(5) assert_equals(pf.value, 25) p2 = Promise() pr = p2.then(None, lambda r: 5) p2.reject("Error") assert_equals(5, pr.value)
def test_3_2_3_1(): """ The second argument to 'then' must be called when a promise is rejected. """ c = Counter() def check(r, c): assert_exception(r, Exception, "Error") c.tick() p1 = Promise() p2 = p1.then(None, lambda r: check(r, c)) p1.reject(Exception("Error")) assert_equals(1, c.value())
def test_3_2_5_2_if(): """ Then can be called multiple times on the same promise and callbacks must be called in the order of the then calls. """ def add(l, v): l.append(v) p1 = Promise() p1.reject("Error") order = [] p2 = p1.then(None, lambda v: add(order, "p2")) p3 = p1.then(None, lambda v: add(order, "p3")) assert_equals(2, len(order)) assert_equals("p2", order[0]) assert_equals("p3", order[1])
def test_3_2_3_2(): """ Make sure callbacks are never called more than once. """ c = Counter() p1 = Promise() p2 = p1.then(None, lambda v: c.tick()) p1.reject("Error") try: # I throw an exception p1.reject("Error") assert False # Should not get here! except AssertionError: # This is expected pass assert_equals(1, c.value())
def test_3_2_3_2(): """ Make sure callbacks are never called more than once. """ c = Counter() p1 = Promise() p2 = p1.then(None, lambda v: c.tick()) p1.reject(Exception("Error")) try: # I throw an exception p1.reject(Exception("Error")) assert False # Should not get here! except AssertionError: # This is expected pass assert_equals(1, c.value())
def test_3_2_5_2_if(): """ Then can be called multiple times on the same promise and callbacks must be called in the order of the then calls. """ def add(l, v): l.append(v) p1 = Promise() p1.reject(Exception("Error")) order = [] p2 = p1.then(None, lambda v: add(order, "p2")) p3 = p1.then(None, lambda v: add(order, "p3")) assert_equals(2, len(order)) assert_equals("p2", order[0]) assert_equals("p3", order[1])
def error_reply(self, req, rcat, pend_reqs): """In case a request could not be sent because of channel unavailability, calls back the methoddomain with an Error. :param req: RequestIndication not sent in time :param rcat: Request Category value on which no channels could be established :param pend_reqs: Sending queue """ resp = Promise() resp.reject(ErrorResponseConfirmation( 504, self.req.method, "No suitable channel could be established")) correlationID = self.req.correlationID contactURI = self.req.contactURI # Remove the req from the sending queue if correlationID in pend_reqs: self.del_req(rcat, correlationID) # When resp is ready, we call back the methoddomain self.__cb(resp, correlationID, contactURI)
def test_3_2_6_2_if(): """ Promises returned by then must be rejected when any of their callbacks throw an exception. """ def fail(v): raise AssertionError("Exception Message") p1 = Promise() p1.fulfill(5) pf = p1.then(fail) assert pf.isRejected() assert_equals("Exception Message", pf.reason) p2 = Promise() p2.reject("Error") pr = p2.then(None, fail) assert pr.isRejected() assert_equals("Exception Message", pr.reason)
def test_3_2_6_2_if(): """ Promises returned by then must be rejected when any of their callbacks throw an exception. """ def fail(v): raise AssertionError("Exception Message") p1 = Promise() p1.fulfill(5) pf = p1.then(fail) assert pf.isRejected assert_exception(pf.reason, AssertionError, "Exception Message") p2 = Promise() p2.reject(Exception("Error")) pr = p2.then(None, fail) assert pr.isRejected assert_exception(pr.reason, AssertionError, "Exception Message")
def test_done(): counter = [0] def inc(_): counter[0] += 1 def dec(_): counter[0] -= 1 p = Promise() p.done(inc, dec) p.fulfill(4) assert_equals(counter[0], 1) p = Promise() p.done(inc, dec) p.done(inc, dec) p.reject(Exception()) assert_equals(counter[0], -1)
def send_request(self, request): p = Promise() if request.method not in (RequestMethod.create, RequestMethod.notify): return p.reject( ErrorResponse(ResponseCode.method_not_allowed, RequestMethod, "text/plain")) request_indication = map_request_to_request_indication(request) notification = request_indication.resource content_type = request_indication.content_type channel_id = urlparse(request_indication.path).path[1:] self.logger.debug("Received notification on channel '%s' (%s)", channel_id, request_indication.path) try: waiting = self.waiting[channel_id] except KeyError: return p.reject(SCLNotFound(request_indication.path)) if waiting: self.waiting[channel_id] = [] response_confirmation = RetrieveResponseConfirmation( notification, content_type) response = map_response_confirmation_to_response( request, response_confirmation) for waiting_promise in waiting: waiting_promise.fulfill(response) else: self.queues[channel_id].append((notification, content_type)) response = map_response_confirmation_to_response( request, NotifyResponseConfirmation()) return p.fulfill(response)
def test_3_2_6_3_when_rejected(): """ Testing return of pending promises to make sure they are properly chained. This covers the case where the root promise is rejected after the chaining is defined. """ p1 = Promise() pending = Promise() pr = p1.then(None, lambda r: pending) assert pending.isPending() assert pr.isPending() p1.reject("Error") pending.fulfill(10) assert pending.isFulfilled() assert_equals(10, pending.value) assert pr.isFulfilled() assert_equals(10, pr.value) p2 = Promise() bad = Promise() pr = p2.then(None, lambda r: bad) assert bad.isPending() assert pr.isPending() p2.reject("Error") bad.reject("Assertion") assert bad.isRejected() assert_equals("Assertion", bad.reason) assert pr.isRejected() assert_equals("Assertion", pr.reason)
def test_3_2_6_3_when_rejected(): """ Testing return of pending promises to make sure they are properly chained. This covers the case where the root promise is rejected after the chaining is defined. """ p1 = Promise() pending = Promise() pr = p1.then(None, lambda r: pending) assert pending.isPending assert pr.isPending p1.reject(Exception("Error")) pending.fulfill(10) assert pending.isFulfilled assert_equals(10, pending.value) assert pr.isFulfilled assert_equals(10, pr.value) p2 = Promise() bad = Promise() pr = p2.then(None, lambda r: bad) assert bad.isPending assert pr.isPending p2.reject(Exception("Error")) bad.reject(Exception("Assertion")) assert bad.isRejected assert_exception(bad.reason, Exception, "Assertion") assert pr.isRejected assert_exception(pr.reason, Exception, "Assertion")
def _do_update_scl(self, scl_path, scl, shelve): """ :param scl_path: str :param scl :param shelve: GEventSQLShelve :return: Promise """ p = Promise() if shelve is not None: shelve.setitem(scl_path, scl) return p.fulfill(shelve) return p.reject(None)
def _update_online_status(self, status): """ Checks if any known poc is listed as onlineStatus """ self.logger.debug("_update_online_status: status: %s %s ", status, type(status)) promise = Promise() if status.statusCode == STATUS_OK: return promise.fulfill(status) else: return promise.reject(status)
def handle_onem2m_request(self, onem2m_request): self.logger.debug("handling request:\r\n\t%s", onem2m_request) db_session = self._api.start_onem2m_session() try: result = self._handle_onem2m_request(db_session, onem2m_request) db_session.commit() return result except Exception as error: if log_error(error): self.logger.exception("Error during request: %r", error) else: self.logger.debug("Error during request: %r", error) try: status_code = error.response_status_code except AttributeError: status_code = 500 p = Promise() result = OneM2MErrorResponse(status_code=status_code, request=onem2m_request) db_session.rollback() p.reject(result) return p
def request(self, method, path, data=None, headers={}, args=None): if isinstance(data, unicode): data = data.encode("utf-8") fullpath = self.__base + path request_headers = self.__headers.copy() if args: fullpath += ("?" in fullpath and "&" or "?") + compose_qs(args) if headers: request_headers.update(headers) if method == "GET": timeout = self.get_timeout try: etag, modified, cached = self.__cache[fullpath] if etag: request_headers["If-None-Match"] = etag request_headers["If-Modified-Since"] = modified except KeyError: request_headers.pop("If-None-Match", None) request_headers.pop("If-Modified-Since", None) else: timeout = self.timeout request_headers.setdefault("Content-Type", self.__content_type) log_headers = request_headers if self.logger.isEnabledFor( DEBUG) and "Authorization" in request_headers: log_headers = request_headers.copy() log_headers["Authorization"] = "<purged>" if method == "GET": self.logger.debug("%s: %s (%s)", method, fullpath, log_headers) else: self.logger.debug("%s: %s (%s)\n%s", method, fullpath, log_headers, repr(data)) #t = time() promise = Promise() try: #response = self.__connection_manager.request(method, fullpath, data, request_headers, timeout) def response_handler(resp): if resp.status_code == 304: try: promise.fulfill(closing(StringIO(cached))) except NameError: promise.reject( NetworkError( "Error: The %s returned 304 though no cached version is available. Request was: %s %s" % (self.component_name, method, fullpath))) if resp.status_code < 200 or resp.status_code >= 300: try: promise.reject( HTTPError(msg=resp.status_message, status=resp.status_code)) except: promise.reject( HTTPError(msg="Http error", status=response.status)) else: promise.fulfill(resp) req = self.client.request(method, fullpath, response_handler) for head, value in request_headers.items(): req.put_header(head, value) if data: req.chunked = True req.write_str(data) req.end() except Exception as e: print "Exception triggered: %s" % e promise.reject(e) return promise
def handle_aggregation(self, request_indication): """Handles aggregation for request_indications where path starts with aggregate:///""" p = Promise() # check if really notify if request_indication.method != "notify": return p.reject(SCLMethodNotAllowed(request_indication.method)) path = urlparse(request_indication.path).path[1:] self.logger.debug("aggregating for path: %s", path) # missing content_type signals me unparsed resource, so parse it ct = request_indication.content_type if ct: serializer = get_serializer(ct) typename, resource = serializer.decode(request_indication.resource) self.logger.debug("decoded resource: %s - %s", resource, typename) data = resource data["requestingEntity"] = request_indication.requestingEntity else: data = request_indication.resource data["requestingEntity"] = request_indication.requestingEntity self.logger.debug("Set requestingEntity to %s", request_indication.requestingEntity) # TODO: use dict.get() # check if there's a running aggregation for the path already # if so, just add the notify and promise to the maps if path in aggregate_data.ncolmap and len( aggregate_data.ncolmap[path]) > 0: aggregate_data.ncolmap[path].append(data) aggregate_data.ncolpromises[path].append(p) self.logger.debug("added notification to database, size: %s", len(aggregate_data.ncolmap[path])) # otherwise, start a timer and create ney keys in the maps else: self.logger.debug("no pending notifies for %s", path) aggregate_data.ncolmap[path] = [data] aggregate_data.ncolpromises[path] = [p] try: dtol = aggregate_data.ncoldelaytolerance[path] except KeyError: # FIXME (ren) put default delay tolerance somewhere dtol = 10 # to be fired after delaytolerance timer is over def dtol_handler(): self.logger.debug("dtol_handler FIRING") payload = list(aggregate_data.ncolmap[path]) promises = list(aggregate_data.ncolpromises[path]) # remove path from maps aggregate_data.ncolmap.pop(path, None) aggregate_data.ncolpromises.pop(path, None) # FIXME (ren): from log: "Specifying typename is deprecated" notify_req_ind = NotifyRequestIndication( path, {"notify": payload}, typename="notifyCollection") self.logger.debug("dtol_handler sends collection: %s", payload) def finished(response): # fulfill each pending promise of the original notifies result = NotifyResponseConfirmation() for pending_p in promises: pending_p.fulfill(result) self.logger.debug("confirmed %s notifications for: %s", len(promises), path) return self.api.send_request_indication(notify_req_ind).then( finished) self.logger.debug("starting dtol_handler, countdown: %s seconds", dtol) self.api.set_timer(dtol, dtol_handler) return p
def testNonFunction(nonFunction, results): def foo(results, k, r): results[k] = r p1 = Promise() p2 = p1.then(nonFunction, lambda r: foo(results, str(nonFunction), r)) p1.reject("Error: "+str(nonFunction))