def verify_io(iolist, expected, any_order=False, echo=True): if echo: print("%s:: %s" % (len(iolist), '\n '.join(fmap(str, iolist)))) expected_type = [E[0] for E in expected] for each in iolist: if not expected: # Unexpected or too many response messages assert str(each) == expected_type if isinstance(each, (LogAggregator, LostRemote, HysteresisCancel)): if any_order: assert type(each) in expected_type expi = expected_type.index(type(each)) else: assert type(each) == expected_type[0] expi = 0 v = each, None else: # Either TransmitIntent or HysteresisSend; currently no # way to expclitly test for the latter without extending # `expected` if any_order: assert type(each.message) in expected_type expi = expected_type.index(type(each.message)) else: assert type(each.message) == expected_type[0] expi = 0 v = each.message, each.targetAddr if expected[expi][1]: assert expected[expi][1](*v), \ 'Validation of (%s): %s' % (type(each), fmap(str, each)) del expected[expi] del expected_type[expi] # Did not see these remaining expected messages assert not expected_type
def _updateStatusResponse(self, resp): "Called to update a Thespian_SystemStatus or Thespian_ActorStatus with common information" for each in self.childAddresses: resp.addChild(each) for each in self._receiveQueue: resp.addReceivedMessage(each.sender, self.myAddress, each.message) self._sCBStats.copyToStatusResponse(resp) resp.governer = str(self._governer) fmap(lambda x: resp.addTXPendingAddressCount(*len_second(x)), self._awaitingAddressUpdate) self.transport._updateStatusResponse(resp)
def protectedFileNumList(self): return fmap( lambda s: s.fileno(), filter(None, [self.socket] + [I.socket for I in self._incomingSockets] + [ I.socket for I in self._transmitIntents if hasattr(I, 'socket') ]))
def test_fmap_recursive(self): result = fmap(lambda x: x*2, ([10,11], (23,24), ([31,32], [42,(55,66)]), fmap_obj(zip(filter(lambda y: y < 10, range(3)), map(lambda y: y + 3, range(3)))))) # Arg: realize all of the iterables, since python3 returns things like map objects and filter objects # but comparing those to an actual list fails. That's what all the list(result...) stuff is below. print(len(result)) assert [[20, 22], [46, 48], [[62,64], [84,(110,132)]], [(0,6), (2,8), (4,10)]] == \ [list(result[0]), list(result[1]), [list(result[2][0]), list(result[2][1])], list(result[3].vals())]
def got_system_shutdown(self): gen_ops = lambda addr: [ HysteresisCancel(addr), TransmitIntent(addr, ConventionDeRegister(self.myAddress)), ] if self.conventionLeaderAddr and \ self.conventionLeaderAddr != self.myAddress: thesplog('Admin de-registering with Convention @ %s', str(self.conventionLeaderAddr), level=logging.INFO, primary=True) return gen_ops(self.conventionLeaderAddr) return join( fmap(gen_ops, [ M.remoteAddress for M in self._conventionMembers.values() if M.remoteAddress != self.myAddress ]))
def verifyExpectedResponses(self, asys, target, requestMsg, expected): resp = asys.ask(target, requestMsg, MAX_ASK_DELAY) if expected == None: assert resp is None else: while resp and expected: for n, e in enumerate(expected): if hasattr(e, 'search'): if e.search(resp): break else: if e == resp: break else: assert False, 'Expected "%s" not found in: %s' % ( resp, fmap(str, expected)) del expected[n] resp = asys.listen(0.1) assert len(expected) == 0
def verifyExpectedResponses(self, asys, target, requestMsg, expected): resp = asys.ask(target, requestMsg, MAX_ASK_DELAY) if expected == None: assert resp is None else: while resp and expected: for n,e in enumerate(expected): if hasattr(e, 'search'): if e.search(resp): break else: if e == resp: break else: assert False, 'Expected "%s" not found in: %s'%( resp, fmap(str, expected)) del expected[n] resp = asys.listen(0.1) assert len(expected) == 0
def exit_convention(self): self.invited = False gen_ops = lambda addr: [HysteresisCancel(addr), TransmitIntent(addr, ConventionDeRegister(self.myAddress)), ] terminate = lambda a: [ self._remote_system_cleanup(a), gen_ops(a) ][-1] if self.conventionLeaderAddr and \ self.conventionLeaderAddr != self.myAddress: thesplog('Admin de-registering with Convention @ %s', str(self.conventionLeaderAddr), level=logging.INFO, primary=True) # Cache convention leader address because it might get reset by terminate() claddr = self.conventionLeaderAddr terminate(self.conventionLeaderAddr) return gen_ops(claddr) return join(fmap(terminate, [M.remoteAddress for M in self._conventionMembers.values() if M.remoteAddress != self.myAddress]))
def test_fmap_tuple(self): assert (0,2,4,6,8) == fmap(lambda x: x*2, (0,1,2,3,4))
def _runWithExpiry(self, incomingHandler): xmitOnly = incomingHandler == TransmitOnly or \ isinstance(incomingHandler, TransmitOnly) if hasattr(self, '_aborting_run'): delattr(self, '_aborting_run') while not self.run_time.expired() and \ (not hasattr(self, '_aborting_run') or (self._aborting_run and self._transmitIntents)): if xmitOnly: if not self._transmitIntents: return 0 else: while self._incomingEnvelopes: rEnv = self._incomingEnvelopes.pop(0) if incomingHandler is None: return rEnv if not incomingHandler(rEnv): return None wsend, wrecv = fmap( TCPTransport._socketFile, partition( TCPTransport._waitForSendable, filter(lambda T: not T.backoffPause(), self._transmitIntents))) wrecv = list(filter(None, wrecv)) wsend = list(filter(None, wsend)) wrecv.extend( list( filter(None, [ TCPTransport._socketFile(I) for I in self._incomingSockets if not I.backoffPause() ]))) delays = list([ R for R in [self.run_time.remaining()] + [T.delay() for T in self._transmitIntents] + [T.delay() for T in self._incomingSockets] if R is not None ]) delay = timePeriodSeconds(min(delays)) if delays else None if not hasattr(self, '_aborting_run') and not xmitOnly: wrecv.extend([self.socket.fileno()]) # rrecv, rsend, _ign2 = select.select(wrecv, wsend, [], delay) try: rrecv, rsend, _ign2 = select.select(wrecv, wsend, set(wsend + wrecv), delay) except ValueError as ex: thesplog('ValueError on select(#%d: %s, #%d: %s, #%d: %s, %s)', len(wrecv), wrecv, len(wsend), wsend, len(set(wsend + wrecv)), set(wsend + wrecv), delay, level=logging.ERROR) raise except select.error as ex: if ex.args[0] in ( errno.EINVAL, # probably a change in descriptors errno.EINTR, ): thesplog('select retry on %s', ex, level=logging.ERROR) continue raise if _ign2: thesplog('WHOA... something else to do for sockets: %s', _ign2, level=logging.WARNING) origPendingSends = len(self._transmitIntents) # Handle newly sendable data for eachs in rsend: self._transmitIntents = [ I for I in self._transmitIntents if self._nextTransmitStepCheck(I, eachs) ] # Handle newly receivable data for each in rrecv: if each == self.socket.fileno(): self._acceptNewIncoming() continue self._incomingSockets = [ S for S in self._incomingSockets if self._handlePossibleIncoming(S, each) ] self._transmitIntents = [ I for I in self._transmitIntents if self._nextTransmitStepCheck(I, each) ] # Handle timeouts self._transmitIntents = [ I for I in self._transmitIntents if self._nextTransmitStepCheck(I, -1) ] self._incomingSockets = [ S for S in self._incomingSockets if self._handlePossibleIncoming(S, -1) ] # Check if it's time to quit if [] == rrecv and [] == rsend: if [] == _ign2 and self.run_time.expired(): # Timeout, give up return None continue if xmitOnly: remXmits = len(self._transmitIntents) if origPendingSends > remXmits or remXmits == 0: return remXmits # Handle queued internal "received" data if not xmitOnly: while self._incomingEnvelopes: rEnv = self._incomingEnvelopes.pop(0) if incomingHandler is None: return rEnv if not incomingHandler(rEnv): return None return None
def _runWithExpiry(self, incomingHandler): xmitOnly = incomingHandler == TransmitOnly or \ isinstance(incomingHandler, TransmitOnly) if hasattr(self, '_aborting_run'): delattr(self, '_aborting_run') while not self.run_time.expired() and \ (not hasattr(self, '_aborting_run') or (self._aborting_run and self._transmitIntents)): if xmitOnly: if not self._transmitIntents: return 0 else: while self._incomingEnvelopes: rEnv = self._incomingEnvelopes.pop(0) if incomingHandler is None: return rEnv if not incomingHandler(rEnv): return None wsend, wrecv = fmap(TCPTransport._socketFile, partition(TCPTransport._waitForSendable, filter(lambda T: not T.backoffPause(), self._transmitIntents))) wrecv = list(filter(None, wrecv)) wsend = list(filter(None, wsend)) wrecv.extend(list(filter(None, [TCPTransport._socketFile(I) for I in self._incomingSockets if not I.backoffPause()]))) delays = list([R for R in [self.run_time.remaining()] + [T.delay() for T in self._transmitIntents] + [T.delay() for T in self._incomingSockets] if R is not None]) delay = timePeriodSeconds(min(delays)) if delays else None if not hasattr(self, '_aborting_run') and not xmitOnly: wrecv.extend([self.socket.fileno()]) # rrecv, rsend, _ign2 = select.select(wrecv, wsend, [], delay) try: rrecv, rsend, _ign2 = select.select(wrecv, wsend, set(wsend+wrecv), delay) except ValueError as ex: thesplog('ValueError on select(#%d: %s, #%d: %s, #%d: %s, %s)', len(wrecv), wrecv, len(wsend), wsend, len(set(wsend + wrecv)), set(wsend + wrecv), delay, level=logging.ERROR) raise except select.error as ex: if ex.args[0] in (errno.EINVAL, # probably a change in descriptors errno.EINTR, ): thesplog('select retry on %s', ex, level=logging.ERROR) continue raise if _ign2: thesplog('WHOA... something else to do for sockets: %s', _ign2, level=logging.WARNING) origPendingSends = len(self._transmitIntents) # Handle newly sendable data for eachs in rsend: self._transmitIntents = [I for I in self._transmitIntents if self._nextTransmitStepCheck(I, eachs)] # Handle newly receivable data for each in rrecv: if each == self.socket.fileno(): self._acceptNewIncoming() continue self._incomingSockets = [S for S in self._incomingSockets if self._handlePossibleIncoming(S, each)] self._transmitIntents = [I for I in self._transmitIntents if self._nextTransmitStepCheck(I, each)] # Handle timeouts self._transmitIntents = [I for I in self._transmitIntents if self._nextTransmitStepCheck(I, -1)] self._incomingSockets = [S for S in self._incomingSockets if self._handlePossibleIncoming(S, -1)] # Check if it's time to quit if [] == rrecv and [] == rsend: if [] == _ign2 and self.run_time.expired(): # Timeout, give up return None continue if xmitOnly: remXmits = len(self._transmitIntents) if origPendingSends > remXmits or remXmits == 0: return remXmits # Handle queued internal "received" data if not xmitOnly: while self._incomingEnvelopes: rEnv = self._incomingEnvelopes.pop(0) if incomingHandler is None: return rEnv if not incomingHandler(rEnv): return None return None
def test_fmap_scalars(self): assert 2 == fmap(lambda x: x*2, 1) assert 5.5 == fmap(lambda x: x*2, 2.75) assert 5 == fmap(lambda x: len(x), "hello")
def test_RegistrationNotificationWithActorAddress(self, asys, asys2): unsupported(asys) notifications = asys.createActor(NotificationHandler) asys.tell(notifications, True) asys.updateCapability('dog', 'food') asys2.updateCapability('barn', 'oats') regActor = asys.createActor(PreRegistrationActor) raises(NoCompatibleSystemForActor, asys.createActor, Horse) raises(NoCompatibleSystemForActor, asys.createActor, Cow) notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) assert not notes print('notification address:',str(notifications)) myaddr = str(notifications).split('|')[1].split(':')[0] print('myaddr:',myaddr) rsp = asys.ask(regActor, ("Register", "%s:%d"%(myaddr, asys2.port_num), {'moo': True}), MAX_ASK_DELAY) wait_for_registration() showAdminStatus(asys) showAdminStatus(asys2) # wait and show should allow actual convention registration for # full set of remote capabilities, then verify that this has # occurred. wait_for_registration() # allow convention registration notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) print(fmap(str, notes)) assert len(notes) == 1 for each in notes: print(':: %s @ %s : %s' % (each.remoteAdded, str(each.remoteAdminAddress), str(each.remoteCapabilities))) assert isinstance(each.remoteAdminAddress, ActorAddress) rmtAdmin = each.remoteAdminAddress # Actual registration should have actual capabilities assert 'barn' in each.remoteCapabilities assert each.remoteCapabilities['barn'] == 'oats' assert 'Thespian Version' in each.remoteCapabilities assert each.remoteAdded horse = asys.createActor(Horse) assert asys.ask(horse, 'bor', MAX_ASK_DELAY) == 'Neigh: bor' # Verify that deregistration can be performed with the remote # admin address and that there is a corresponding # notification. rsp = asys.ask(regActor, ("Deregister", rmtAdmin), MAX_ASK_DELAY) wait_for_registration() showAdminStatus(asys) showAdminStatus(asys2) notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) print(fmap(repr, notes)) assert len(notes) == 1 for each in notes: print(':: %s @ %s : %s' % (each.remoteAdded, str(each.remoteAdminAddress), str(each.remoteCapabilities))) assert isinstance(each.remoteAdminAddress, ActorAddress) # Actual registration should have actual capabilities assert 'barn' in each.remoteCapabilities assert each.remoteCapabilities['barn'] == 'oats' assert 'Thespian Version' in each.remoteCapabilities assert not each.remoteAdded
def test_fmap_mappable_obj(self): assert [0,2,4,6,8] == fmap(lambda x: x*2, fmap_obj([0,1,2,3,4])).vals()
def test_fmap_plain_obj(self): assert 5 == fmap(lambda x: len(x.vals()), plain_obj([0,1,2,3,4]))
def test_fmap_dict(self): assert {0:2, 4:6, 8:10} == fmap(lambda x: x*2, {0:1, 2:3, 4:5})
def test_fmap_zip(self): assert [(0,6), (2,8), (4,10)] == fmap(lambda x: x*2, zip([0,1,2], [3,4,5]))
def test_fmap_filter(self): assert [0,2,4,6,8] == fmap(lambda x: x*2, filter(lambda y: y < 5, range(15)))
def test_fmap_map(self): assert [0,2,4,6,8] == fmap(lambda x: x*2, map(lambda y: y - 1, range(1,6)))
def test_fmap_range(self): assert [0,2,4,6,8] == fmap(lambda x: x*2, range(5))
def protectedFileNumList(self): return fmap(lambda s: s.fileno(), filter(None, [self.socket] + [I.socket for I in self._incomingSockets] + [I.socket for I in self._transmitIntents if hasattr(I, 'socket')]))
def test_fmap_list(self): assert [0,2,4,6,8] == fmap(lambda x: x*2, [0,1,2,3,4])
def fmap(self, f): return fmap_obj(fmap(f, self._sublist))
def test_RegistrationNotificationWithAddressString(self, asys, asys2): unsupported(asys) notifications = asys.createActor(NotificationHandler) asys.tell(notifications, True) asys.updateCapability('dog', 'food') asys2.updateCapability('barn', 'oats') regActor = asys.createActor(PreRegistrationActor) raises(NoCompatibleSystemForActor, asys.createActor, Horse) raises(NoCompatibleSystemForActor, asys.createActor, Cow) notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) assert not notes rsp = asys.ask(regActor, ("Register", "127.0.0.1:%d"%(asys2.port_num), {'moo': True}), MAX_ASK_DELAY) wait_for_registration() showAdminStatus(asys) showAdminStatus(asys2) # wait and show should allow actual conventionregistration for # full set of remote capabilities. notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) print('notes:',fmap(str, notes)) assert len(notes) == 1 for each in notes: assert isinstance(each.remoteAdminAddress, ActorAddress) # Actual registration should have actual capabilities assert 'barn' in each.remoteCapabilities assert each.remoteCapabilities['barn'] == 'oats' assert 'Thespian Version' in each.remoteCapabilities assert each.remoteAdded horse = asys.createActor(Horse) assert asys.ask(horse, 'bor', MAX_ASK_DELAY) == 'Neigh: bor' # Verify that deregistration can be performed with the remote # admin address and that there is a corresponding # notification. rsp = asys.ask(regActor, ("Deregister", "127.0.0.1:%d"%(asys2.port_num)), MAX_ASK_DELAY) wait_for_registration() showAdminStatus(asys) showAdminStatus(asys2) notes = asys.ask(notifications, 'get', MAX_ASK_DELAY) print(fmap(repr, notes)) assert len(notes) == 1 for each in notes: print(':: %s @ %s : %s' % (each.remoteAdded, str(each.remoteAdminAddress), str(each.remoteCapabilities))) assert isinstance(each.remoteAdminAddress, ActorAddress) # Actual registration should have actual capabilities assert 'barn' in each.remoteCapabilities assert each.remoteCapabilities['barn'] == 'oats' assert 'Thespian Version' in each.remoteCapabilities # Still a member because it is distinct from the added # version assert not each.remoteAdded