def test_many_msgs(namebroker): # Send many msgs to one actor, collect them and count them class A(ThreadedActor): def act(self): self.results = {} try: while True: self.receive(add=self.add) except ActorFinished: pass def add(self, msg): self.results[msg['i']] = 1 if list(sorted(self.results.keys())) == list(range(100)): with ActorRef(msg['reply_to']) as sender: sender.got_all() class B(Actor): def act(self): result = [] self.receive(got_all=lambda msg: result.append(True), timed_out=lambda msg: result.append(False), timeout=2) return result # Create many instances to check the pipes are refreshed for each instance actors = [A() for i in range(4)] collector = B() x_ref = ActorRef(actors[-1].address()) for i in range(100): x_ref.add(i=i, reply_to=collector) result = collector.act() assert result == [True] [x.close() for x in actors] collector.close()
def spawn(actor, name=None, ip='localhost', **kwargs): """ Utility function to start a process actor and initialize it """ if name is not None: with ActorRef((name, ip, None)) as ref: # Do not start if it's already alive if ref.is_alive(): return ProcessActorProxy(*ref.full_address()) a = actor() class Wait(Actor): def act(self): self.success = True self.receive( finished_init=None, timed_out=lambda _: setattr(self, 'success', False), timeout=5) return self.success with ActorRef(a.remote_addr) as ref, Wait() as wait: kwargs['ip'] = ip ref.init(reply_to=wait, **kwargs) if wait.act(): remote = list(a.remote_addr) remote[1] = ip return ProcessActorProxy(remote, a.pid) else: raise SpawnTimeoutError('failed to init remote process')
def test_reply(qm): class a(Actor): def act(self): result = [] self.receive({ 'answer': lambda msg: result.append(msg['answer'])}) return result[0] x = a('a') qt = ActorRef('p') qt.send({'tag': 'reply', 'reply_to': 'a'}) assert x.act() == 5
def tick(self, msg): print('tick', self.my_name, self.c) self.c += 1 with ActorRef(msg.reply_to) as sender: sender.tick(reply_to=self) if self.c == self.max: with ActorRef(self.report_to) as ref: ref.report( name=self.my_name, start_time=self.starting_time, end_time=time.time() ) self.receive()
def run(): with Wait() as w, \ spawn(Collector, wait=w.address()) as collector, \ spawn(Ticker, my_name='Ping', c=0, max=10, report_to=collector.address()) as ping, \ spawn(Ticker, my_name='Pong', c=0, max=10, report_to=collector.address()) as pong, \ ActorRef(ping) as ping_ref, \ ActorRef(pong) as pong_ref: print('Starting') ping_ref.set_start_time() pong_ref.set_start_time() ping_ref.tick(reply_to=pong_ref) w.wait()
def test_inbox(namebroker, threaded_actor, answer_actor): with ActorRef(threaded_actor.address()) as t: t.foo() t.bar() t.reply5(reply_to=answer_actor) result = answer_actor.act() assert result == [5]
def test_timeout_zero_no_match(data_actor): with ActorRef(data_actor.address()) as a_ref: a_ref.bar(data=2) while data_actor.inbox.qsize() != 1: time.sleep(0.1) for _ in range(4): result = data_actor.act() assert result is None
def test_none_method(): class A(Actor): def act(self): self.receive(foo=None) return True with A() as a, ActorRef(a.address()) as a_ref: a_ref.foo() result = a.act() assert result
def test_timeout_zero(data_actor): with ActorRef(data_actor.address()) as a_ref: a_ref.foo(data=1) while True: result = data_actor.act() if result is not None: assert result == 1 return time.sleep(0.1)
def test_new_api_2(namebroker): class A(Actor): pass with A() as a, ActorRef(a.address()) as a_ref: with pytest.raises(TypeError): a_ref() a_ref.foo() with pytest.raises(TypeError): a_ref()
def test_timeout_zero_2(data_actor): with ActorRef(data_actor.address()) as a_ref: a_ref.bar() a_ref.baz() a_ref.foo(data=1) a_ref.gii() while data_actor.inbox.qsize() < 4: time.sleep(0.1) result = data_actor.act() assert result == 1
def remote_init(self, msg): """ Save addresses of other actors we want this process to know """ del msg['tag'] for name in msg: setattr(self, name, msg[name]) with ActorRef(msg['reply_to']) as sender: sender.finished_init()
def test_attribute_access(): class A(ThreadedActor): def act(self): self.receive(echo=self.echo) def echo(self, msg): with ActorRef(msg.reply_to) as sender: sender.reply(x=4) with ThreadedActor.spawn(A) as a, ActorRef(a) as a_ref: result = a_ref.sync('echo') assert result['x'] == 4
def test_alive_not_acting(): class A(Actor): def act(self): self.receive(_=self.read_value('tag')) return self.tag with A() as a, ActorRef(a.address()) as a_ref: alive = a_ref.is_alive() assert alive a_ref.foo() result = a.act() assert result == 'foo'
def test_wildcard(namebroker): class A(Actor): def act(self): result = [] self.receive( _ = lambda msg: result.append(msg['tag'])) return result with A() as a, ActorRef(a.address()) as a_ref: a_ref.foo() result = a.act() assert result == ['foo']
def __exit__(self, exc_type, exc_value, traceback): """ Actor context closes it on exit """ try: with ActorRef(self.address()) as myself: myself.close_actor() except PipeException: # If actor was already closed, ignore error from the # reference trying to ping the actor pass
def test_sync_call(): class T(ThreadedActor): def act(self): self.receive(sync_test=self.sync_test) def sync_test(self, msg): with ActorRef(msg['reply_to']) as sender: sender.reply(got=msg) with T() as t, ActorRef(t.address()) as t_ref: assert t_ref.is_alive() answer = t_ref.sync('sync_test', x=5) assert answer['got']['tag'] == 'sync_test' assert answer['got']['x'] == 5
def test_close_actor_and_ref(): class Wait(Actor): def act(self): self.receive(_=None) class T(ThreadedActor): def act(self): self.receive() with T() as t, Wait() as w, ActorRef(t.address()) as t_ref: alive = t_ref.is_alive() assert alive t_ref.close_actor(confirm_to=w.address()) w.act() not_alive = not t_ref.is_alive() assert not_alive
def test_process_close(): with ProcessActor.spawn(EchoProcessActor) as p, ActorRef(p.address()) as p_ref: assert p_ref.is_alive() p_ref.close_actor() assert not p_ref.is_alive() for _ in range(200): try: if os.waitpid(p.pid, os.WNOHANG) == (0, 0): break except ChildProcessError: break time.sleep(0.01) else: assert False
def test_new_api(namebroker): class A(Actor): def act(self): self.receive( foo = self.foo) return self._msg def foo(self, msg): self._msg = msg with A() as a, ActorRef(a.address()) as a_ref: a_ref.foo(bar=3, baz='baz') msg = a.act() assert (msg['tag'] == 'foo' and msg['bar'] == 3 and msg['baz'] == 'baz')
def test_close_with_confirmation(threaded_actor): class A(Actor): def act(self): self.receive(_ = self.read_value('tag')) return self.tag class T(ThreadedActor): def act(self): self.receive() with A() as a, T() as t, ActorRef(t.address()) as t_ref: alive = t_ref.is_alive() assert alive t_ref.close_actor(confirm_to=a.address()) result = a.act() assert result == 'closed' assert not t_ref.is_alive()
def test_timeout_eating_msgs(): result = [True] class A(Actor): def act(self): self.receive(timeout=0.1) def act2(self): self.receive( bar = lambda msg: None, timed_out = lambda msg: result.append(False), timeout = 0.1) with A() as a, ActorRef(a.address()) as a_ref: a_ref.bar() while a.inbox.qsize() != 1: time.sleep(0.1) a.act() a.act2() assert result[-1]
def test_timeout_zero_2(qm): class a(Actor): def act(self): self.receive({ 'foo': self.read_value('data'), }, timeout=0) return getattr(self, 'data', None) x = a() y = ActorRef(x.name) y.send({'tag': 'bar'}) y.send({'tag': 'baz'}) y.send({'tag': 'foo', 'data': 1}) y.send({'tag': 'gii'}) while x.inbox.qsize() < 4: time.sleep(0.1) z = x.act() assert z == 1
def test_threaded_spawn_with_args_fast(): class T(ThreadedActor): def act(self): assert self.x == 0 self.receive(get_x=self.get_x) def get_x(self, msg): with ActorRef(msg.reply_to) as sender: sender.reply(x=self.x) class W(Actor): def act(self): self.x = 1 self.receive( reply=self.read_value('x'), timeout=0.5 ) return self.x with ThreadedActor.spawn(T, x=0) as t, ActorRef(t) as t_ref, W() as w: t_ref.get_x(reply_to=w) result = w.act() assert result == 0
def test_threaded_spawn_with_args(): class T(ThreadedActor): def act(self): self.receive( args = self.args ) def args(self, msg): with ActorRef(msg['reply_to']) as sender: sender.reply(x=self.x, k=self.k) class A(Actor): def act(self): self.receive( reply = self.reply ) return self.x, self.k def reply(self, msg): self.x = msg['x'] self.k = msg['k'] with ThreadedActor.spawn(T, x=5, k='a') as t, ActorRef(t.address()) as t_ref, A() as a: assert t_ref.is_alive() t_ref.args(reply_to=a.address()) result = a.act() assert result == (5, 'a')
def test_reply_to_proxy(process_actor): with ActorRef(process_actor) as ref: ref.foo(reply_to=process_actor) assert ref.is_alive()
def __init__(self): super(PEcho, self).__init__() def act(self): while True: self.receive(_=self.do_pecho) def do_pecho(self, msg): print('Process Echo:') print(msg) if __name__ == '__main__': _, wait_name, actor_class, actor_module, class_dir = sys.argv sys.path.insert(0, class_dir) mod = importlib.import_module(actor_module) cls = getattr(mod, actor_class) # Signal the base class ``ProcessActor`` to not start a new # subprocess (we are already in it!) cls.launch = False with cls() as actor, ActorRef(wait_name, remote=False) as wait: # Tell parent to keep going wait.ok(spawn_address=actor.address(), pid=os.getpid()) # The new process ends when the client's actor finishes its # ``act`` method. try: actor._act() except KeyboardInterrupt: pass
def echo(self, msg): with ActorRef(msg['reply_to']) as sender: del msg['tag'] sender.reply(**msg)
def test_many_msgs(nb): # Send many msgs to one actor, collect them and count them class a(ThreadedActor): def __init__(self): super(a, self).__init__() self.results = {} def act(self): try: while True: self.receive(add=self.add) except ActorFinished: pass def add(self, msg): self.results[msg['i']] = 1 if sorted(self.results.keys()) == range(100): with ActorRef(msg['reply_to']) as sender: sender.got_all() class b(Actor): def act(self): result = [] self.receive(got_all=lambda msg: result.append(True), timed_out=lambda msg: result.append(False), timeout=2) return result # Create many instances to check the pipes are refreshed for each instance actors = [a() for i in range(4)] y = b() x_ref = ActorRef(actors[-1].address()) for i in range(100): x_ref.add(i=i, reply_to=y) res = y.act() assert res == [True] [x.close() for x in actors] y.close() # def test_reply(p): # class a(Actor): # def act(self): # result = [] # self.receive( # answer = lambda msg: result.append(msg['answer'])) # return result[0] # x = a('a') # qt = ActorRef('p') # qt.send({'tag': 'reply', # 'reply_to': 'a'}) # assert x.act() == 5 # x.close() # def test_inbox(p): # class a(Actor): # def act(self): # result = [] # self.receive({ # 'answer': lambda msg: result.append(msg['answer'])}) # return result[0] # x = a('a') # qt = ActorRef('p') # qt.send({'tag': 'foo'}) # qt.send({'tag': 'bar'}) # qt.send({'tag': 'queue', # 'reply_to': 'a'}) # assert x.act() == 2 # x.close() # def test_non_existent_actor_ref(): # x = ActorRef('foobar') # not_alive = not x.is_alive() # assert not_alive # not_alive = not x.is_alive() # assert not_alive # x.close() # def test_existent_actor_ref(t, p): # x = ActorRef('t') # alive = x.is_alive() # assert alive # y = ActorRef('p') # alive = y.is_alive() # assert alive # x.close() # y.close() # def test_timeout_zero(): # class a(Actor): # def act(self): # self.receive({ # 'foo': self.read_value('data'), # }, timeout=0) # return getattr(self, 'data', None) # x = a() # ActorRef(x.name).send({'tag': 'foo', 'data': 1}) # while x.act() is None: # time.sleep(0.1) # y = x.act() # assert y == 1 # x.close() # def test_timeout_zero_2(): # class a(Actor): # def act(self): # self.receive({ # 'foo': self.read_value('data'), # }, timeout=0) # return getattr(self, 'data', None) # x = a() # y = ActorRef(x.name) # y.send({'tag': 'bar'}) # y.send({'tag': 'baz'}) # y.send({'tag': 'foo', 'data': 1}) # y.send({'tag': 'gii'}) # while x.inbox.qsize() < 4: # time.sleep(0.1) # z = x.act() # assert z == 1 # x.close() # def test_timeout_zero_no_match(): # class a(Actor): # def act(self): # self.receive({ # 'foo': self.read_value('data') # }, timeout=0) # return getattr(self, 'data', None) # x = a() # ActorRef(x.name).send({'tag': 'bar', 'data': 2}) # while x.inbox.qsize() != 1: # time.sleep(0.1) # y = x.act() # y = x.act() # y = x.act() # y = x.act() # assert y == None # x.close() # def test_timeout_eating_msgs(): # result = [True] # class a(Actor): # def act(self): # self.receive({}, timeout=0.1) # def act2(self): # self.receive( # bar = lambda msg: None, # timed_out = lambda msg: result.append(False), # timeout = 0.1) # x = a() # ActorRef(x.name).send({'tag': 'bar'}) # while x.inbox.qsize() != 1: # time.sleep(0.1) # x.act() # x.act2() # assert result[-1] # x.close() # def test_process_actor_returns_name(q): # p, _ = spawn(q, 'foo') # ref = ActorRef('foo') # assert p == 'foo' # ActorRef('foo').close_actor() # def test_process_with_arg(q2): # class a(Actor): # def act(self): # self.receive(reply = self.read_value('x')) # return self.x # x = a() # spawn(q2, 'foo2', x=5) # ref = ActorRef('foo2') # ref.get_x(reply_to=x.name) # u = x.act() # assert u == 5 # ref.close_actor() # x.close() # def test_close_with_confirmation(t): # class a(Actor): # def act(self): # self.receive(_ = self.read_value('tag')) # return self.tag # x = a() # with ActorRef('t') as tr: # alive = tr.is_alive() # assert alive # tr.close_actor(confirm_to=x.name) # u = x.act() # assert u == 'closed' # x.close() # def test_ping(): # class a(ThreadedActor): # def act(self): # try: # self.receive(foo=lambda msg: None) # except ActorFinished: # pass # x = a() # xr = ActorRef(x.name) # alive = xr.is_alive() # assert alive # time.sleep(0.5) # alive = xr.is_alive() # assert alive # x.close() # def test_none_method(): # class a(Actor): # def act(self): # self.receive(foo=None) # return True # x = a() # xr = ActorRef(x.name) # xr.foo() # y = x.act() # assert y # x.close() # def test_close_actor_and_ref(): # class Wait(Actor): # def act(self): # self.receive(_=None) # class a(ThreadedActor): # def act(self): # self.receive() # x = a() # wait = Wait() # xr = ActorRef(x.name) # alive = xr.is_alive() # assert alive # xr.close_actor(confirm_to=wait.name) # wait.act() # not_alive = not xr.is_alive() # assert not_alive # x.close() # wait.close() # def test_sync_call(t): # class a(ThreadedActor): # def act(self): # self.receive(sync_test=self.sync_test) # def sync_test(self, msg): # with ActorRef(msg['reply_to']) as sender: # sender.reply(got=msg) # x = a() # with ActorRef(x.name) as tr: # assert tr.is_alive() # answer = tr.sync('sync_test', x=5) # assert answer['got']['tag'] == 'sync_test' # assert answer['got']['x'] == 5 # x.close() # def test_alive_not_acting(): # class a(Actor): # def act(self): # self.receive(_=self.read_value('tag')) # return self.tag # x = a() # xr = ActorRef(x.name) # alive = xr.is_alive() # assert alive # xr.foo() # u = x.act() # assert u == 'foo'
def test_ref_with_proxy(process_actor): with ActorRef(process_actor) as ref: assert ref.is_alive()
def echo(self, msg): with ActorRef(msg.reply_to) as sender: sender.reply(x=4)
def test_ref_with_ref(threaded_actor): with ActorRef(threaded_actor) as t_ref: with ActorRef(t_ref) as x_ref: assert t_ref.address() == x_ref.address()
def reply2(self, msg): sender = ActorRef(msg['reply_to']) sender.answer(answer=2)
def test_ref_with_actor(threaded_actor): with ActorRef(threaded_actor) as t_ref: assert t_ref.address() == threaded_actor.address()