def fetch_wavelet(self, wave_id, wavelet_id=None, proxy_for_id=None, raw_deltas_from_version=-1, return_raw_snapshot=False): """Use the REST interface to fetch a wave and return it. The returned wavelet contains a snapshot of the state of the wavelet at that point. It can be used to modify the wavelet, but the wavelet might change in between, so treat carefully. Also note that the wavelet returned has its own operation queue. It the responsibility of the caller to make sure this wavelet gets submited to the server, either by calling robot.submit() or by calling .submit_with() on the returned wavelet. Args: wave_id: the wave id wavelet_id: the wavelet_id proxy_for_id: on whose behalf to execute the operation raw_deltas_from_version: If specified, return a raw dump of the delta history of this wavelet, starting at the given version. This may return only part of the history; use additional requests with higher raw_deltas_from_version parameters to get the rest. return_raw_snapshot: if true, return the raw data for this wavelet. """ util.check_is_valid_proxy_for_id(proxy_for_id) if not wavelet_id: domain, id = wave_id.split('!', 1) wavelet_id = domain + '!conv+root' operation_queue = ops.OperationQueue(proxy_for_id) operation_queue.robot_fetch_wave(wave_id, wavelet_id, raw_deltas_from_version, return_raw_snapshot) result = self._first_rpc_result(self.make_rpc(operation_queue)) return self._wavelet_from_json(result, ops.OperationQueue(proxy_for_id))
def testConstructModifyTag(self): q = ops.OperationQueue() op = q.wavelet_modify_tag('waveid', 'waveletid', 'tag') self.assertEqual(3, len(op.params)) op = q.wavelet_modify_tag( 'waveid', 'waveletid', 'tag', modify_how='remove') self.assertEqual(4, len(op.params))
def testWaveletBlipMethods(self): operation_queue = ops.OperationQueue() TEST_DATA = simplejson.loads(testdata.json_string) w = self.waveservice._wavelet_from_json(TEST_DATA, operation_queue) root_blip = w.root_blip blip = root_blip.continue_thread() self.assertEquals(blip.parent_blip_id, root_blip.parent_blip_id) self.assertEquals(8, len(w.blips)) self.assertEquals(4, len(w.root_thread.blips))
def fetch_wavelet(self, wave_id, wavelet_id, proxy_for_id=None): """Use the REST interface to fetch a wave and return it. The returned wavelet contains a snapshot of the state of the wavelet at that point. It can be used to modify the wavelet, but the wavelet might change in between, so treat carefully. Also note that the wavelet returned has its own operation queue. It the responsibility of the caller to make sure this wavelet gets submited to the server, either by calling robot.submit() or by calling .submit_with() on the returned wavelet. """ operation_queue = ops.OperationQueue(proxy_for_id) operation_queue.robot_fetch_wave(wave_id, wavelet_id) result = self._first_rpc_result(self.make_rpc(operation_queue)) return self._wavelet_from_json(result, ops.OperationQueue(proxy_for_id))
def setUp(self): self.operation_queue = ops.OperationQueue() self.all_blips = {} self.blip = blip.Blip(TEST_BLIP_DATA, self.all_blips, self.operation_queue) self.all_blips[self.blip.blip_id] = self.blip self.wavelet = wavelet.Wavelet(TEST_WAVELET_DATA, self.all_blips, None, self.operation_queue) self.wavelet.robot_address = ROBOT_NAME
def testSerialize(self): q = ops.OperationQueue() q.set_capability_hash('hash') op = q.wavelet_modify_tag('waveid', 'waveletid', 'tag') json = q.serialize() self.assertEqual(2, len(json)) self.assertEqual('robot.notify', json[0]['method']) self.assertEqual('hash', json[0]['params']['capabilitiesHash']) self.assertEqual(ops.PROTOCOL_VERSION, json[0]['params']['protocolVersion']) self.assertEqual('wavelet.modifyTag', json[1]['method'])
def search(self, query, index=None, num_results=None): """Execute a search request. Args: query: what to search for, for example [in:inbox] index: index of the first result to return num_results: how many results to return """ operation_queue = ops.OperationQueue() operation_queue.robot_search(query, index, num_results) result = self._first_rpc_result(self.make_rpc(operation_queue)) return search.Results(result)
def testConstructRobotFetchWave(self): q = ops.OperationQueue('proxyid') op = q.robot_fetch_wave('wave1', 'wavelet1') self.assertEqual(3, len(op.params)) self.assertEqual('proxyid', op.params['proxyingFor']) self.assertEqual('wave1', op.params['waveId']) self.assertEqual('wavelet1', op.params['waveletId']) op = q.robot_fetch_wave('wave1', 'wavelet1', raw_deltas_from_version=5, return_raw_snapshot=True) self.assertEqual(5, len(op.params)) self.assertEqual(5, op.params['rawDeltasFromVersion']) self.assertEqual(True, op.params['returnRawSnapshot'])
def setUp(self): self.operation_queue = ops.OperationQueue() self.all_blips = {} self.blip = blip.Blip(TEST_BLIP_DATA, self.all_blips, self.operation_queue) self.all_blips[self.blip.blip_id] = self.blip root_thread_data = TEST_WAVELET_DATA.get('rootThread') root_thread = wavelet.BlipThread('', root_thread_data.get('location'), root_thread_data.get('blipIds', []), self.all_blips, self.operation_queue) self.wavelet = wavelet.Wavelet(TEST_WAVELET_DATA, self.all_blips, root_thread, self.operation_queue) self.wavelet.robot_address = ROBOT_NAME
def process_events(self, json): """Process an incoming set of events encoded as json.""" parsed = simplejson.loads(json) pending_ops = ops.OperationQueue() event_wavelet = self._wavelet_from_json(parsed, pending_ops) for event_data in parsed['events']: for payload in self._handlers.get(event_data['type'], []): handler, event_class, context, filter = payload event = event_class(event_data, event_wavelet) handler(event, event_wavelet) pending_ops.set_capability_hash(self.capabilities_hash()) return simplejson.dumps(pending_ops.serialize())
def testWaveletProperties(self): operation_queue = ops.OperationQueue() TEST_DATA = simplejson.loads(testdata.json_string) w = self.waveservice._wavelet_from_json(TEST_DATA, operation_queue) self.assertEquals(TEST_DATA['wavelet']['waveId'], w.wave_id) self.assertEquals(TEST_DATA['wavelet']['rootThread']['id'], w.root_thread.id) self.assertEquals(TEST_DATA['wavelet']['rootThread']['location'], w.root_thread.location) self.assertEquals(len(TEST_DATA['wavelet']['rootThread']['blipIds']), len(w.root_thread.blips)) b = w.root_blip self.assertEquals(len(TEST_DATA['blips']['b+IvD7RCuWB']['replyThreadIds']), len(b.reply_threads))
def blind_wavelet(self, json, proxy_for_id=None): """Construct a blind wave from a json string. Call this method if you have a snapshot of a wave that you want to operate on outside of an event. Since the wave might have changed since you last saw it, you should take care to submit operations that are as safe as possible. Args: json: a json object or string containing at least a key wavelet defining the wavelet and a key blips defining the blips in the view. proxy_for_id: the proxying information that will be set on the wavelet's operation queue. Returns: A new wavelet with its own operation queue. It the responsibility of the caller to make sure this wavelet gets submited to the server, either by calling robot.submit() or by calling .submit_with() on the returned wavelet. """ return self._wavelet_from_json(json, ops.OperationQueue(proxy_for_id))
def make_rpc(self, operations): """Make an rpc call, submitting the specified operations.""" rpc_host = urlparse.urlparse(self._server_rpc_base).netloc # We either expect an operationqueue, a single op or a list # of ops: if (not isinstance(operations, ops.OperationQueue)): if not isinstance(operations, list): operations = [operations] queue = ops.OperationQueue() queue.copy_operations(operations) else: queue = operations data = simplejson.dumps(queue.serialize(method_prefix='wave')) oauth_request = oauth.OAuthRequest.from_consumer_and_token(self._consumer, token=self._access_token, http_method='POST', http_url=self._server_rpc_base) oauth_request.sign_request(WaveService.SIGNATURE_METHOD, self._consumer, self._access_token) logging.info('Active URL: %s' % self._server_rpc_base) logging.info('Active Outgoing: %s' % data) headers = {'Content-Type': 'application/json'} headers.update(oauth_request.to_header()); status, content = self._http_post( url=self._server_rpc_base, data=data, headers=headers) if status != 200: raise errors.RpcError('code: %s\n%s' % (status, content)) return simplejson.loads(content)
def setUp(self): self.all_blips = {} self.operation_queue = ops.OperationQueue()
def new_wave(self, domain, participants=None, message='', proxy_for_id=None, submit=False): """Create a new wave with the initial participants on it. A new wave is returned with its own operation queue. It the responsibility of the caller to make sure this wave gets submitted to the server, either by calling robot.submit() or by calling .submit_with() on the returned wave. Args: domain: the domain to create the wavelet on. This should in general correspond to the domain of the incoming wavelet. (wavelet.domain). Exceptions are situations where the robot is calling new_wave outside of an event or when the server is handling multiple domains. participants: initial participants on the wave. The robot as the creator of the wave is always added. message: a string that will be passed back to the robot when the WAVELET_CREATOR event is fired. This is a lightweight way to pass around state. submit: if true, use the active gateway to make a round trip to the server. This will return immediately an actual waveid/waveletid and blipId for the root blip. """ util.check_is_valid_proxy_for_id(proxy_for_id) operation_queue = ops.OperationQueue(proxy_for_id) if not isinstance(message, basestring): message = simplejson.dumps(message) # Create temporary wavelet data blip_data, wavelet_data = operation_queue.robot_create_wavelet( domain=domain, participants=participants, message=message) # Create temporary blips dictionary blips = {} root_blip = blip.Blip(blip_data, blips, operation_queue) blips[root_blip.blip_id] = root_blip if submit: # Submit operation to server and return actual wave/blip IDs temp_wavelet = wavelet.Wavelet(wavelet_data, blips=blips, root_thread=None, operation_queue=operation_queue) result = self._first_rpc_result(self.submit(temp_wavelet)) if isinstance(result, list): result = result[0] if 'blipId' in result: blip_data['blipId'] = result['blipId'] wavelet_data['rootBlipId'] = result['blipId'] for field in 'waveId', 'waveletId': if field in result: wavelet_data[field] = result[field] blip_data[field] = result[field] blips = {} root_blip = blip.Blip(blip_data, blips, operation_queue) blips[root_blip.blip_id] = root_blip root_thread = wavelet.BlipThread('', -1, [root_blip.blip_id], blips, operation_queue) new_wavelet = wavelet.Wavelet(wavelet_data, blips=blips, root_thread=root_thread, operation_queue=operation_queue) return new_wavelet
def new_wave(self, domain, participants=None, message='', proxy_for_id=None, submit=False): """Create a new wave with the initial participants on it. A new wave is returned with its own operation queue. It the responsibility of the caller to make sure this wave gets submitted to the server, either by calling robot.submit() or by calling .submit_with() on the returned wave. Args: domain: the domain to create the wavelet on. This should in general correspond to the domain of the incoming wavelet. (wavelet.domain). Exceptions are situations where the robot is calling new_wave outside of an event or when the server is handling multiple domains. participants: initial participants on the wave. The robot as the creator of the wave is always added. message: a string that will be passed back to the robot when the WAVELET_CREATOR event is fired. This is a lightweight way to pass around state. submit: if true, use the active gateway to make a round trip to the server. This will return immediately an actual waveid/waveletid and blipId for the root blip. """ operation_queue = ops.OperationQueue(proxy_for_id) if not isinstance(message, basestring): message = simplejson.dumps(message) blip_data, wavelet_data = operation_queue.robot_create_wavelet( domain=domain, participants=participants, message=message) blips = {} root_blip = blip.Blip(blip_data, blips, operation_queue) blips[root_blip.blip_id] = root_blip created = wavelet.Wavelet(wavelet_data, blips=blips, robot=self, operation_queue=operation_queue) if submit: result = self._first_rpc_result(self.submit(created)) if type(result) == list: result = result[0] # Currently, data is sometimes wrapped in an outer 'data' # Remove these 2 lines when that is no longer an issue. if 'data' in result and len(result) == 2: result = result['data'] if 'blipId' in result: blip_data['blipId'] = result['blipId'] wavelet_data['rootBlipId'] = result['blipId'] for field in 'waveId', 'waveletId': if field in result: wavelet_data[field] = result[field] blip_data[field] = result[field] blips = {} root_blip = blip.Blip(blip_data, blips, operation_queue) blips[root_blip.blip_id] = root_blip created = wavelet.Wavelet(wavelet_data, blips=blips, robot=self, operation_queue=operation_queue) return created