def test_shaped(self): self.assertEquals( shape.is_shaped("hello", str), True) self.assertEquals( shape.is_shaped(1, int), True) self.assertEquals( shape.is_shaped([1, 2, 3], [int]), True) self.assertEqual( shape.is_shaped(set([8,9]), set([int])), True) self.assertEqual( shape.is_shaped({'a':'b','c':5}, {'a':str,'c':int}), True) self.assertEqual( shape.is_shaped((1,'a'),(int,str)), True) self.assertEqual( shape.is_shaped(['x'],set([str])), True), self.assertEqual( shape.is_shaped(['x'],set(['x'])), True) self.assertEqual( shape.is_shaped(set(['x']), [str]), True) self.assertEqual( shape.is_shaped(set(['x']), ['x']), True)
def test_not_shaped(self): self.assertRaises( shape.TypeMismatch, shape.is_shaped_exc, 1, str) self.assertRaises( shape.TypeMismatch, shape.is_shaped_exc, [1, 2, 3], bool) self.assertRaises( shape.TypeMismatch, shape.is_shaped_exc, {'hello': 'world'}, int) self.assertEqual( shape.is_shaped(1, bool), False) self.assertRaises( shape.TypeMismatch, shape.is_shaped_exc, {'hello': 'world'}, 5) self.assertEqual( shape.is_shaped(1,2), False) self.assertEqual( shape.is_shaped(str,"z"), False) self.assertEqual( shape.is_shaped(7,['a','b']), False) self.assertEqual( shape.is_shaped((1,2,3),(int,int)), False) self.assertEqual( shape.is_shaped(1,{'a':100}), False) self.assertEqual( shape.is_shaped([1,2,3],(int,int,int)), False)
def _match_patterns(self,patterns): """Internal method to match a list of patterns against the mailbox. If message matches any of the patterns, that message is removed from the mailbox and returned along with the pattern it matched. If message doesn't match any pattern then None,None is returned. """ for i, message in enumerate(self._mailbox): for pattern in patterns: if shape.is_shaped(message, pattern): del self._mailbox[i] return pattern, message return None,None
def test_deep_nesting(self): self.assertEquals( shape.is_shaped( { 'hello': 1, 'world': [{ 'abc': 'def' }, { 'abc': 'def' }] }, { 'hello': int, 'world': [{ 'abc': str }] }), True)
def test_not_shaped(self): self.assertRaises(shape.TypeMismatch, shape.is_shaped_exc, 1, str) self.assertRaises(shape.TypeMismatch, shape.is_shaped_exc, [1, 2, 3], bool) self.assertRaises(shape.TypeMismatch, shape.is_shaped_exc, {'hello': 'world'}, int) self.assertEqual(shape.is_shaped(1, bool), False) self.assertRaises(shape.TypeMismatch, shape.is_shaped_exc, {'hello': 'world'}, 5) self.assertEqual(shape.is_shaped(1, 2), False) self.assertEqual(shape.is_shaped(str, "z"), False) self.assertEqual(shape.is_shaped(7, ['a', 'b']), False) self.assertEqual(shape.is_shaped((1, 2, 3), (int, int)), False) self.assertEqual(shape.is_shaped(1, {'a': 100}), False) self.assertEqual(shape.is_shaped([1, 2, 3], (int, int, int)), False)
def respond_exception(self, orig_message, exception): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message['address'].cast({'response':orig_message['call'], 'exception':exception})
def test_exact_match(self): self.assertEquals( shape.is_shaped({'hello': 'world'}, {'hello': 'world'}), True)
def respond(self, orig_message, response=None): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message['address'].cast({'response':orig_message['call'], 'message':response})
def respond_invalid_method(self, orig_message, method): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message['address'].cast({'response':orig_message['call'], 'invalid_method':method})
def test_deep_nesting(self): self.assertEquals( shape.is_shaped( {'hello': 1, 'world': [{'abc': 'def'}, {'abc': 'def'}]}, {'hello': int, 'world': [{'abc': str}]}), True)
def test_tuple_shaped(self): self.assertEquals( shape.is_shaped((1, "hello", True), (int, str, bool)), True)
def test_tuple_shaped(self): self.assertEquals( shape.is_shaped( (1, "hello", True), (int, str, bool)), True)
def respond_exception(self, orig_message, exception): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message["address"].cast({"response": orig_message["call"], "exception": exception})
class ActorApplication(object): def __call__(self, env, start_response): path = env['PATH_INFO'][1:] method = 'do_'+env['REQUEST_METHOD'] if hasattr(self,method): return getattr(self,method)(path,env,start_response) def do_PUT(self,path,env,start_response): if not path: start_response('405 Method Not Allowed', [('Content-type', 'text/plain')]) return 'Method Not Allowed\n' new_actor = EvalActor.spawn(path, env['wsgi.input'].read(int(env['CONTENT_LENGTH']))) start_response('202 Accepted', [('Content-type', 'text/plain')]) return 'Accepted\n' def do_POST(self,path,env,start_response): local_address = 'http://%s/' % (env['HTTP_HOST'], ) old_actor = actor.Actor.all_actors.get(path) if old_actor is None: start_response('404 Not Found', [('Content-type', 'text/plain')]) return "Not Found\n" try: body = env['wsgi.input'].read(int(env['CONTENT_LENGTH'])) def generate_custom(obj): if obj.keys() == ['address']: address = obj['address'] if address.startswith(local_address): obj = {'address': address[len(local_address):]} return actor.generate_custom(obj) msg = actor.json.loads(body, object_hook=generate_custom) except Exception, e: traceback.print_exc() start_response('406 Not Acceptable', [('Content-type', 'text/plain')]) return 'Not Acceptable\n' if not shape.is_shaped(msg,actor.REMOTE_CALL_PATTERN): old_actor.address.cast(msg) start_response('202 Accepted', [('Content-type', 'text/plain')]) return 'Accepted\n' # handle a remote call try: rmsg = LocalCaller.spawn(local_addr=old_actor.address, message_id=msg['remotecall'], method=msg['method'], message=msg['message'], timeout=msg['timeout']).wait() except eventlet.TimeoutError: start_response('408 Request Timeout',[('Content-type','text/plain')]) return actor.json.dumps({'timeout':msg['timeout']})+'\n' resp_str = actor.json.dumps(rmsg, default=_remote_handle_custom)+'\n' if shape.is_shaped(rmsg, RSP_PAT): start_response('202 Accepted',[('Content-type','application/json')]) elif shape.is_shaped(rmsg, INV_PAT): start_response('404 Not Found',[('Content-type','application/json')]) else: start_response('406 Not Acceptable',[('Content-type','application/json')]) return resp_str
def respond_invalid_method(self, orig_message, method): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message["address"].cast({"response": orig_message["call"], "invalid_method": method})
def respond(self, orig_message, response=None): if not shape.is_shaped(orig_message, CALL_PATTERN): raise InvalidCallMessage(str(orig_message)) orig_message["address"].cast({"response": orig_message["call"], "message": response})
def test_dict_shape(self): self.assertEquals( shape.is_shaped({'foo': 1}, {'foo': int}), True)
def test_dict_shape(self): self.assertEquals(shape.is_shaped({'foo': 1}, {'foo': int}), True)
def test_list_shape(self): self.assertEquals(shape.is_shaped([1, 2, 3], [int]), True)
def test_exact_match(self): self.assertEquals( shape.is_shaped( {'hello': 'world'}, {'hello': 'world'}), True)
def test_list_shape(self): self.assertEquals( shape.is_shaped([1, 2, 3], [int]), True)