Ejemplo n.º 1
0
def test_expression_valid_single_value() -> None:
    code_string = 1
    expr = Expression(code_string)
    assert expr.code_string == str(code_string)
    assert expr.evaluate(EvaluationContext()) == 1

    code_string = False
    expr = Expression(code_string)
    assert expr.code_string == str(code_string)
    assert expr.evaluate(EvaluationContext()) is False

    code_string = '"Hello World"'
    expr = Expression(code_string)
    assert expr.code_string == code_string
    assert expr.evaluate(EvaluationContext()) == "Hello World"

    code_string = '[1, 2, 3]'
    expr = Expression(code_string)
    assert expr.code_string == code_string
    assert expr.evaluate(EvaluationContext()) == [1, 2, 3]

    code_string = '{"a":1, "b":2}'
    expr = Expression(code_string)
    assert expr.code_string == code_string
    assert expr.evaluate(EvaluationContext()) == {"a": 1, "b": 2}
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    def context(self) -> EvaluationContext:
        if self._context:
            return self._context
        # The eval code adds the python global context to the global context dict being passed and
        # new context being created is added to the local context. We take the local_context in
        # temp_eval_context and use that as the global context for the returned EvaluationContext.
        temp_eval_context = EvaluationContext()
        for import_statement in self.import_statements:
            import_statement.evaluate(temp_eval_context)

        eval_context = EvaluationContext(
            global_context=temp_eval_context.local_context)

        return eval_context
Ejemplo n.º 5
0
def test_expression_globals_locals() -> None:
    code_string = 'a + b + 1'
    expr = Expression(code_string)

    with pytest.raises(NameError, match='name \'a\' is not defined'):
        expr.evaluate(EvaluationContext())

    assert expr.evaluate(EvaluationContext(Context({'a': 2, 'b': 3}))) == 6
    assert expr.evaluate(
        EvaluationContext(local_context=Context({
            'a': 2,
            'b': 3
        }))) == 6
    assert expr.evaluate(
        EvaluationContext(Context({'a': 2}), Context({'b': 3}))) == 6
Ejemplo n.º 6
0
def create_block_aggregate(schema, time, identity) -> BlockAggregate:
    evaluation_context = EvaluationContext()
    block_aggregate = BlockAggregate(schema=schema,
                                     identity=identity,
                                     evaluation_context=evaluation_context)
    evaluation_context.global_add('time', time)
    evaluation_context.global_add('user', block_aggregate)
    evaluation_context.global_add('identity', identity)
    return block_aggregate
Ejemplo n.º 7
0
def test_execution_key_error(caplog) -> None:
    caplog.set_level(logging.DEBUG)
    code_string = 'test_dict[\'missing_key\'] + 1'
    assert Expression(code_string).evaluate(
        EvaluationContext(Context({'test_dict': {}}))) is None
    assert 'KeyError in evaluating expression test_dict[\'missing_key\'] + 1. Error: \'missing_key\'' in caplog.records[
        0].message
    assert caplog.records[0].levelno == logging.DEBUG
Ejemplo n.º 8
0
def test_execution_error_type_mismatch(caplog) -> None:
    caplog.set_level(logging.DEBUG)
    code_string = '1 + \'a\''
    assert Expression(code_string).evaluate(
        EvaluationContext(Context({'test_dict': {}}))) is None
    assert 'TypeError in evaluating expression 1 + \'a\'' in caplog.records[
        0].message
    assert caplog.records[0].levelno == logging.DEBUG
Ejemplo n.º 9
0
def test_aggregate_finalize(aggregate_schema_with_store):
    aggregate = MockAggregate(schema=aggregate_schema_with_store,
                              identity="12345",
                              evaluation_context=EvaluationContext())
    aggregate.run_finalize()
    snapshot_aggregate = aggregate._store.get(
        Key(identity="12345", group="user"))
    assert snapshot_aggregate is not None
    assert snapshot_aggregate == aggregate._snapshot
Ejemplo n.º 10
0
def test_expression_user_function() -> None:
    code_string = '2 if test_function() else 3'

    def test_function():
        return 3 > 4

    expr = Expression(code_string)
    assert expr.evaluate(
        EvaluationContext(Context({'test_function': test_function}))) == 3
Ejemplo n.º 11
0
def test_aggregate_persist_with_store(aggregate_schema_with_store):
    aggregate = MockAggregate(
        schema=aggregate_schema_with_store,
        identity="12345",
        evaluation_context=EvaluationContext())
    aggregate._persist()
    snapshot_aggregate = aggregate._store.get(
        Key(KeyType.DIMENSION, identity="12345", group="user"))
    assert snapshot_aggregate is not None
    assert snapshot_aggregate == aggregate._snapshot
Ejemplo n.º 12
0
def test_get_attribute_invalid(collection_schema_spec: Dict[str, Any],
                               mock_nested_items: contextmanager) -> None:
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec(collection_schema_spec)
    schema_collection = MockBaseSchemaCollection(
        name, schema_loader, AggregateSchema.ATTRIBUTE_FIELDS)

    with raises(Exception):
        item_collection = MockBaseItemCollection(schema_collection,
                                                 EvaluationContext())
        assert item_collection.event_counts

    # Test nested items not specified
    with mock_nested_items:
        with raises(Exception):
            item_collection = MockBaseItemCollection(schema_collection,
                                                     EvaluationContext())
            mock_nested_items.return_value = None
            assert item_collection.event_count
Ejemplo n.º 13
0
def test_aggregate_nested_items(aggregate_schema_with_store):
    aggregate = MockAggregate(schema=aggregate_schema_with_store,
                              identity="12345",
                              evaluation_context=EvaluationContext())
    nested_items = aggregate._nested_items
    assert len(nested_items) == 2
    assert "event_count" in nested_items
    assert isinstance(nested_items["event_count"], Field)
    assert "_identity" in nested_items
    assert isinstance(nested_items["_identity"], Field)
Ejemplo n.º 14
0
 def _load_blocks(self, blocks: List[Tuple[Key, Any]]) -> List[BlockAggregate]:
     """
     Converts [(Key, block)] to [BlockAggregate]
     :param blocks: List of (Key, block) blocks.
     :return: List of BlockAggregate
     """
     return [
         BlockAggregate(self._schema.source, self._identity,
                        EvaluationContext()).run_restore(block) for (_, block) in blocks
     ]
Ejemplo n.º 15
0
def test_execution_error_missing_field(caplog,
                                       schema_loader: SchemaLoader) -> None:
    caplog.set_level(logging.DEBUG)
    context = Context({
        'test':
        StreamingTransformer(schema_loader.get_schema_object('test'), 'user1')
    })
    with raises(MissingAttributeError,
                match='missing_field not defined in test_group'):
        Expression('test.test_group.missing_field').evaluate(
            EvaluationContext(context))
    assert (
        'MissingAttributeError in evaluating expression test.test_group.missing_field. '
        'Error: missing_field not defined in test_group') in caplog.text

    with raises(MissingAttributeError,
                match='missing_field not defined in test_group'):
        Expression('test.test_group[\'missing_field\']').evaluate(
            EvaluationContext(context))
Ejemplo n.º 16
0
def test_evaluate_needs_evaluation_false(
        collection_schema_spec: Dict[str, Any]) -> None:
    schema_loader = SchemaLoader()
    collection_schema_spec['When'] = 'False'
    name = schema_loader.add_schema_spec(collection_schema_spec)
    schema_collection = MockBaseSchemaCollection(
        name, schema_loader, AggregateSchema.ATTRIBUTE_FIELDS)
    item_collection = MockBaseItemCollection(schema_collection,
                                             EvaluationContext())
    item_collection.run_evaluate()
    assert item_collection.event_count == 0
Ejemplo n.º 17
0
def test_aggregate_persist_with_store(aggregate_schema_with_store):
    aggregate = MockAggregate(schema=aggregate_schema_with_store,
                              identity="12345",
                              evaluation_context=EvaluationContext())
    dt = datetime.now()
    dt.replace(tzinfo=timezone.utc)
    aggregate._persist(dt)
    snapshot_aggregate = aggregate._store.get(
        Key(identity="12345", group="user", timestamp=dt))
    assert snapshot_aggregate is not None
    assert snapshot_aggregate == aggregate._snapshot
Ejemplo n.º 18
0
def test_get_attribute(collection_schema_spec: Dict[str, Any]) -> None:
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec(collection_schema_spec)
    schema_collection = MockBaseSchemaCollection(
        name, schema_loader, AggregateSchema.ATTRIBUTE_FIELDS)
    item_collection = MockBaseItemCollection(schema_collection,
                                             EvaluationContext())
    # Check nested items access
    assert item_collection.event_count == 0
    # make sure normal properties are not broken
    assert item_collection._schema == schema_collection
Ejemplo n.º 19
0
def block_item(block_schema: BlockAggregateSchema) -> BlockAggregate:
    block = BlockAggregate(block_schema, 'user1', EvaluationContext())
    block.run_restore({
        'events':
        3,
        '_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()
    })
    return block
Ejemplo n.º 20
0
def test_field_evaluate_implicit_typecast_integer():
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'max_attempts',
        'Type': Type.INTEGER,
        'Value': '23.45'
    })
    field_schema = IntegerFieldSchema(name, schema_loader)
    field = Field(field_schema, EvaluationContext())
    field.run_evaluate()

    assert field._snapshot == 23
Ejemplo n.º 21
0
def test_field_evaluate_implicit_typecast_bool():
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'max_attempts',
        'Type': Type.BOOLEAN,
        'Value': '1+2'
    })
    field_schema = BooleanFieldSchema(name, schema_loader)
    field = Field(field_schema, EvaluationContext())
    field.run_evaluate()

    assert field._snapshot is True
Ejemplo n.º 22
0
def test_evaluate_no_separation(
        activity_aggregate_schema: ActivityAggregateSchema,
        activity_events: List[Record]) -> None:
    # Initialize the starting state
    identity = 'user1'
    evaluation_context = EvaluationContext()
    evaluation_context.global_add('identity', identity)
    activity_aggregate = ActivityAggregate(activity_aggregate_schema, identity,
                                           evaluation_context)
    evaluation_context.global_add(activity_aggregate._schema.name,
                                  activity_aggregate)

    store_state = activity_aggregate._store.get_all(identity)
    assert len(store_state) == 0

    evaluate_event(activity_events[0], activity_aggregate)
    activity_aggregate._persist()

    store_state = activity_aggregate._store.get_all(identity)
    assert len(store_state) == 1

    evaluate_event(activity_events[1], activity_aggregate)
    activity_aggregate._persist()

    store_state = activity_aggregate._store.get_all(identity)
    assert len(store_state) == 1
Ejemplo n.º 23
0
def test_split_when_label_evaluates_to_none(
        identity_aggregate_schema_spec: Dict[str, Any],
        store_spec: Dict[str, Any], records: List[Record]):
    identity_aggregate_schema_spec['Dimensions'][0][
        'Value'] = '1/0 if source.label == \'a\' else source.label'
    schema = identity_aggregate_schema(identity_aggregate_schema_spec,
                                       store_spec)
    # Initialize the starting state
    identity = 'user1'
    evaluation_context = EvaluationContext()
    evaluation_context.global_add('identity', identity)
    identity_aggregate = IdentityAggregate(schema, identity,
                                           evaluation_context)
    evaluation_context.global_add(identity_aggregate._schema.name,
                                  identity_aggregate)

    # Check for error states
    evaluate_event(records[0], identity_aggregate)
    evaluate_event(records[1], identity_aggregate)
    evaluate_event(records[2], identity_aggregate)
    assert identity_aggregate._dimension_fields['label'].value == 'b'

    identity_aggregate.run_finalize()

    store_state = identity_aggregate._store.get_all(identity)
    assert len(store_state) == 1

    assert store_state.get(Key('user1', 'label_aggr.b')) == {
        '_identity': 'user1',
        'label': 'b',
        'sum': 1,
        'count': 1
    }
Ejemplo n.º 24
0
def test_field_evaluate_without_needs_evaluation():
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'max_attempts',
        'Type': Type.INTEGER,
        'Value': 5,
        'When': '2 == 3'
    })
    field_schema = MockFieldSchema(name, schema_loader)
    field = MockField(field_schema, EvaluationContext())
    field.run_evaluate()

    assert field.value == 0
Ejemplo n.º 25
0
def test_snapshot_invalid(collection_schema_spec: Dict[str, Any],
                          mock_nested_items: contextmanager) -> None:
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec(collection_schema_spec)
    schema_collection = MockBaseSchemaCollection(
        name, schema_loader, AggregateSchema.ATTRIBUTE_FIELDS)

    # Test nested items not specified
    with mock_nested_items:
        with raises(SnapshotError):
            item_collection = MockBaseItemCollection(schema_collection,
                                                     EvaluationContext())
            assert item_collection._snapshot
Ejemplo n.º 26
0
def aggregate(aggregate_schema: AggregateSchema) -> Aggregate:
    context = EvaluationContext()

    dg = VariableAggregate(schema=aggregate_schema, identity="12345", evaluation_context=context)
    context.global_add('test', dg)
    context.global_add('identity', "12345")

    return dg
Ejemplo n.º 27
0
def test_set_field_snapshot_decoding():
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'test',
        'Type': Type.SET,
        'Value': 'test.add(0).add(1)'
    })
    field_schema = SetFieldSchema(name, schema_loader)
    field = Field(field_schema, EvaluationContext())
    field.run_restore([2, 3])

    assert field.value == {2, 3}
    assert field._snapshot
    assert isinstance(field._snapshot, list)
    assert set(field._snapshot) == field.value
Ejemplo n.º 28
0
def test_set_field_snapshot_encoding():
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'test',
        'Type': Type.SET,
        'Value': 'test.add(0).add(1)'
    })
    field_schema = SetFieldSchema(name, schema_loader)
    field = Field(field_schema, EvaluationContext())
    field._evaluation_context.global_add('test', field.value)
    field.run_evaluate()

    assert field.value == {0, 1}
    assert field._snapshot
    assert isinstance(field._snapshot, list)
    assert set(field._snapshot) == field.value
Ejemplo n.º 29
0
def test_aggregate_final_state(
        activity_aggregate_schema: ActivityAggregateSchema,
        activity_events: List[Record]) -> None:
    # Initialize the starting state
    identity = 'user1'
    evaluation_context = EvaluationContext()
    evaluation_context.global_add('identity', identity)
    activity_aggregate = ActivityAggregate(activity_aggregate_schema, identity,
                                           evaluation_context)
    evaluation_context.global_add(activity_aggregate._schema.name,
                                  activity_aggregate)

    for record in activity_events:
        evaluate_event(record, activity_aggregate)

    activity_aggregate.run_finalize()

    store_state = activity_aggregate._store.get_all(identity)
    assert len(store_state) == 3
    assert store_state.get(
        Key('user1', 'activity_aggr',
            datetime(2018, 1, 1, 1, 1, 1, 0, timezone.utc))) == {
                '_identity': 'user1',
                '_start_time': datetime(2018, 1, 1, 1, 1, 1, 0,
                                        timezone.utc).isoformat(),
                '_end_time': datetime(2018, 1, 1, 1, 2, 1, 0,
                                      timezone.utc).isoformat(),
                'sum': 111,
                'count': 3
            }

    assert store_state.get(
        Key('user1', 'activity_aggr',
            datetime(2018, 1, 1, 3, 1, 1, 0, timezone.utc))) == {
                '_identity': 'user1',
                '_start_time': datetime(2018, 1, 1, 3, 1, 1, 0,
                                        timezone.utc).isoformat(),
                '_end_time': datetime(2018, 1, 1, 3, 1, 1, 0,
                                      timezone.utc).isoformat(),
                'sum': 1000,
                'count': 1
            }

    assert store_state.get(
        Key('user1', 'activity_aggr',
            datetime(2018, 1, 2, 1, 1, 1, 0, timezone.utc))) == {
                '_identity': 'user1',
                '_start_time': datetime(2018, 1, 2, 1, 1, 1, 0,
                                        timezone.utc).isoformat(),
                '_end_time': datetime(2018, 1, 2, 1, 1, 1, 0,
                                      timezone.utc).isoformat(),
                'sum': 10000,
                'count': 1
            }
Ejemplo n.º 30
0
def test_field_evaluate_incorrect_typecast_to_type_default(caplog):
    caplog.set_level(logging.DEBUG)
    schema_loader = SchemaLoader()
    name = schema_loader.add_schema_spec({
        'Name': 'max_attempts',
        'Type': Type.INTEGER,
        'Value': '"Hi"'
    })
    field_schema = IntegerFieldSchema(name, schema_loader)
    field = Field(field_schema, EvaluationContext())
    field.run_evaluate()

    assert field.value == 0
    assert (
        'ValueError in casting Hi to Type.INTEGER for field max_attempts. Error: invalid '
        'literal for int() with base 10: \'Hi\'') in caplog.records[0].message
    assert caplog.records[0].levelno == logging.DEBUG