def test_remove(self): self.assertEqual([Remove( ('a', ), 1), Remove(('b', ), 2)], statediff.diff({ 'a': 1, 'b': 2 }, {}))
def _emit_safe_queued_states(self, force=False): # State messages that occured before the least recently flushed record are safe to emit. # If they occurred after some records that haven't yet been flushed, they aren't safe to emit. # Because records arrive at different rates from different streams, we take the earliest unflushed record # as the threshold for what STATE messages are safe to emit. We ignore the threshold of 0 for streams that # have been registered (via a SCHEMA message) but where no records have arrived yet. valid_flush_watermarks = [] for stream, watermark in self.stream_flush_watermarks.items(): if stream in self.streams_added_to: valid_flush_watermarks.append(watermark) safe_flush_threshold = min(valid_flush_watermarks, default=0) emittable_state = None while len(self.state_queue) > 0 and ( force or self.state_queue[0]['watermark'] <= safe_flush_threshold): emittable_state = self.state_queue.popleft()['state'] if emittable_state: if len( statediff.diff(emittable_state, self.last_emitted_state or {})) > 0: line = json.dumps(emittable_state) sys.stdout.write("{}\n".format(line)) sys.stdout.flush() self.last_emitted_state = emittable_state
def test_null_at_leaf(self): self.assertEqual([Change(('a', ), 1, None), Change(('b', ), None, 2)], statediff.diff({ 'a': 1, 'b': None }, { 'a': None, 'b': 2 }))
def test_change(self): self.assertEqual([Change( ('a', ), 1, 100), Change(('b', ), 2, 200)], statediff.diff({ 'a': 1, 'b': 2 }, { 'a': 100, 'b': 200 }))
def merge(self, state): d = diff(self, state) for m in d: t = self if isinstance(m, Add) or isinstance(m, Change): for i, p in enumerate(m.path): if i == len(m.path) - 1: t[p] = m.newval else: if p not in t: t[p] = {} t = t[p] elif isinstance(m, Remove): pass
def _emit_safe_queued_states(self, force=False): # State messages that occured before the least recently flushed record are safe to emit. # If they occurred after some records that haven't yet been flushed, they aren't safe to emit. # Because records arrive at different rates from different streams, we take the earliest unflushed record as the threshold for what # STATE messages are safe to emit. all_flushed_watermark = min(self.stream_flush_watermarks.values(), default=0) emittable_state = None while len(self.state_queue) > 0 and (force or self.state_queue[0][1] <= all_flushed_watermark): emittable_state = self.state_queue.popleft()[0] if emittable_state: if len(statediff.diff(emittable_state, self.last_emitted_state or {})) > 0: line = json.dumps(emittable_state) sys.stdout.write("{}\n".format(line)) sys.stdout.flush() self.last_emitted_state = emittable_state
def test_null_input_for_both(self): self.assertEqual([], statediff.diff(None, None))
def test_null_input_for_new(self): self.assertEqual([Remove(('a', ), 1)], statediff.diff({'a': 1}, None))
def test_null_input_for_old(self): self.assertEqual([Add(('a', ), 1)], statediff.diff(None, {'a': 1}))
def test_add(self): self.assertEqual([Add(('a', ), 1), Add(('b', ), 2)], statediff.diff({}, { 'a': 1, 'b': 2 }))