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
def __init__(self, fully_qualified_name: str, schema_loader: SchemaLoader) -> None: super().__init__(fully_qualified_name, schema_loader) self.identity = Expression( self._spec[self.ATTRIBUTE_IDENTITY] ) if self.ATTRIBUTE_IDENTITY in self._spec else None self.time = Expression(self._spec[self.ATTRIBUTE_TIME] ) if self.ATTRIBUTE_TIME in self._spec else None
class StreamingTransformerSchema(TransformerSchema): """ Represents the schema for processing streaming data. Handles the streaming specific attributes of the schema """ ATTRIBUTE_IDENTITY = 'Identity' ATTRIBUTE_TIME = 'Time' def __init__(self, fully_qualified_name: str, schema_loader: SchemaLoader) -> None: super().__init__(fully_qualified_name, schema_loader) self.identity = Expression( self._spec[self.ATTRIBUTE_IDENTITY] ) if self.ATTRIBUTE_IDENTITY in self._spec else None self.time = Expression(self._spec[self.ATTRIBUTE_TIME] ) if self.ATTRIBUTE_TIME in self._spec else None def validate_schema_spec(self) -> None: super().validate_schema_spec() self.validate_required_attributes(self.ATTRIBUTE_IDENTITY, self.ATTRIBUTE_TIME, self.ATTRIBUTE_STORES) def get_identity(self, record: Record) -> str: """ Evaluates and returns the identity as specified in the schema. :param record: Record which is used to determine the identity. :return: The evaluated identity :raises: IdentityError if identity cannot be determined. """ context = self.schema_context.context context.add_record(record) identity = self.identity.evaluate(context) if not identity: raise IdentityError( 'Could not determine identity using {}. Record is {}'.format( self.identity.code_string, record)) context.remove_record() return identity def get_time(self, record: Record) -> datetime: context = self.schema_context.context context.add_record(record) time = self.time.evaluate(context) if not time or not isinstance(time, datetime): raise TimeError( 'Could not determine time using {}. Record is {}'.format( self.time.code_string, record)) context.remove_record() return time
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
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
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))
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
def test_expression_conditional() -> None: code_string = '1 if 2 > 1 else 3' expr = Expression(code_string) assert expr.evaluate(EvaluationContext()) == 1
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}
def test_execution_error(caplog) -> None: caplog.set_level(logging.DEBUG) code_string = '1/0' assert Expression(code_string).evaluate(EvaluationContext()) is None assert 'ZeroDivisionError in evaluating expression 1/0. Error: division by zero' in caplog.text
def test_invalid_expression() -> None: code_string = '{9292#?&@&^' with raises(InvalidExpressionError): Expression(code_string)
def test_invalid_expression() -> None: code_string = '{9292#?&@&^' with raises(Exception): Expression(code_string)