def test_anchor_max_two(anchor_schema_max_two: AnchorSchema, block_item: BlockAggregate) -> None: anchor = Anchor(anchor_schema_max_two) assert anchor.evaluate_anchor(block_item, EvaluationContext()) is True anchor.add_condition_met() assert anchor.evaluate_anchor(block_item, EvaluationContext()) is True anchor.add_condition_met() assert anchor.evaluate_anchor(block_item, EvaluationContext()) is False
def test_anchor_max_not_specified(anchor_schema_max_one: AnchorSchema, block_item: BlockAggregate) -> None: anchor_schema_max_one.max = None anchor = Anchor(anchor_schema_max_one) assert anchor.evaluate_anchor(block_item, EvaluationContext()) is True anchor.add_condition_met() assert anchor.evaluate_anchor(block_item, EvaluationContext()) is True anchor.add_condition_met() assert anchor.evaluate_anchor(block_item, EvaluationContext()) is True
def test_anchor_condition(anchor_schema_max_one: AnchorSchema, block_item: BlockAggregate) -> None: anchor_schema_max_one.condition = Expression('session.events > 3') eval_context = EvaluationContext() anchor = Anchor(anchor_schema_max_one) eval_context.local_context.add(block_item._schema.fully_qualified_name, block_item) assert anchor.evaluate_anchor(block_item, eval_context) is False block_item.run_restore({ 'events': 4, '_start_time': datetime(2018, 3, 7, 22, 36, 31, 0, timezone.utc).isoformat(), '_end_time': datetime(2018, 3, 7, 22, 37, 31, 0, timezone.utc).isoformat() }) assert anchor.evaluate_anchor(block_item, eval_context) is True anchor.add_condition_met() assert anchor.evaluate_anchor(block_item, eval_context) is False
def __init__(self, schema: WindowTransformerSchema, identity: str, context: Context) -> None: super().__init__(schema, identity) self._evaluation_context.merge(EvaluationContext(context)) self._anchor = Anchor(schema.anchor)
class WindowTransformer(Transformer): """ The Window DTC transformer that performs window operations on pre-aggregated block data. """ def __init__(self, schema: WindowTransformerSchema, identity: str, context: Context) -> None: super().__init__(schema, identity) self._evaluation_context.merge(EvaluationContext(context)) self._anchor = Anchor(schema.anchor) def run_evaluate(self, block: BlockAggregate) -> bool: """ Evaluates the anchor condition against the specified block. :param block: Block to run the anchor condition against. :return: True, if the anchor condition is met, otherwise, False. """ if self._anchor.evaluate_anchor(block, self._evaluation_context): try: self.run_reset() self._evaluation_context.global_add('anchor', block) self._evaluate() self._anchor.add_condition_met() return True finally: self._evaluation_context.global_remove('anchor') return False def _evaluate(self): if 'anchor' not in self._evaluation_context.global_context or self._anchor.anchor_block is None: raise AnchorBlockNotDefinedError() if not self._needs_evaluation: return for item in self._nested_items.values(): if isinstance(item, WindowAggregate): item._prepare_window(self._anchor.anchor_block._start_time) super().run_evaluate() @property def run_flattened_snapshot(self) -> Dict: """ Generates a flattened snapshot where the final key for a field is <aggregate_name>.<field_name>. :return: The flattened snapshot. """ snapshot_dict = super()._snapshot # Flatten to feature dict return self._flatten_snapshot(None, snapshot_dict) def _flatten_snapshot(self, prefix: Optional[str], value: Dict) -> Dict: flattened_dict = {} for k, v in value.items(): if isinstance(v, dict): flattened_dict.update(self._flatten_snapshot(k, v)) else: flattened_dict[prefix + '.' + k if prefix is not None else k] = v return flattened_dict