Skip to content

Commit 907f356

Browse files
authored
feat: support null-conditional operator (#147)
1 parent e85fc19 commit 907f356

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

src/data_factory_testing_framework/_expression_runtime/data_factory_expression/expression_transformer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def __init__(self) -> None:
4040

4141
expression_grammar = f"""
4242
expression_start: "@" expression_evaluation
43-
expression_evaluation: (expression_logical_bool | expression_branch | expression_call) ((("." EXPRESSION_PARAMETER_NAME) | EXPRESSION_ARRAY_INDEX)+)? EXPRESSION_WS*
43+
expression_evaluation: (expression_logical_bool | expression_branch | expression_call) ((EXPRESSION_NULL_CONDITIONAL_OPERATOR? (expression_field_reference | EXPRESSION_ARRAY_INDEX))+)? EXPRESSION_WS*
4444
?expression_call: expression_function_call
4545
// used to translate to expression_pipeline_reference
4646
| expression_datafactory_parameters_reference
@@ -55,9 +55,8 @@ def __init__(self) -> None:
5555
expression_datafactory_parameters_reference: EXPRESSION_DATAFACTORY_REFERENCE "()"
5656
expression_datafactory_activity_reference: "activity" "(" EXPRESSION_ACTIVITY_NAME ")"
5757
expression_item_reference: "item" "()"
58-
expression_pipeline_reference: "pipeline" "()" "." EXPRESSION_PIPELINE_PROPERTY
59-
60-
58+
expression_pipeline_reference: "pipeline" "()" EXPRESSION_NULL_CONDITIONAL_OPERATOR? "." EXPRESSION_PIPELINE_PROPERTY
59+
expression_field_reference: "." EXPRESSION_PARAMETER_NAME
6160
6261
// branch rules
6362
expression_logical_bool: EXPRESSION_LOGICAL_BOOL "(" expression_parameter "," expression_parameter ")"
@@ -83,6 +82,7 @@ def __init__(self) -> None:
8382
EXPRESSION_STRING: SINGLE_QUOTED_STRING
8483
EXPRESSION_SYSTEM_VARIABLE_NAME: /[a-zA-Z0-9_]+/
8584
EXPRESSION_VARIABLE_NAME: "'" /[^']*/ "'"
85+
EXPRESSION_NULL_CONDITIONAL_OPERATOR: "?"
8686
EXPRESSION_WS: WS
8787
""" # noqa: E501
8888

tests/unit/functions/test_data_factory_testing_framework_expression_evaluator.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,65 @@ def test_evaluate_function_names_are_case_insensitive() -> None:
368368
assert evaluated_value == "ab"
369369

370370

371+
def test_evaluate_function_with_null_conditional_operator() -> None:
372+
# Arrange
373+
expression = "@pipeline().parameters.parameter.field1?.field2"
374+
expression_runtime = ExpressionRuntime()
375+
state = PipelineRunState(
376+
parameters=[
377+
RunParameter(
378+
RunParameterType.Pipeline,
379+
"parameter",
380+
{
381+
"field1": {"field2": "value1"},
382+
},
383+
),
384+
]
385+
)
386+
387+
# Act
388+
evaluated_value = expression_runtime.evaluate(expression, state)
389+
390+
# Assert
391+
assert evaluated_value == "value1"
392+
393+
394+
def test_evaluate_function_with_null_conditional_operator_and_null_value() -> None:
395+
# Arrange
396+
expression = "@pipeline().parameters.parameter?.field1?.field2"
397+
expression_runtime = ExpressionRuntime()
398+
state = PipelineRunState(
399+
parameters=[
400+
RunParameter(
401+
RunParameterType.Pipeline,
402+
"parameter",
403+
{
404+
"field1": None,
405+
},
406+
),
407+
]
408+
)
409+
410+
# Act
411+
evaluated_value = expression_runtime.evaluate(expression, state)
412+
413+
# Assert
414+
assert evaluated_value is None
415+
416+
417+
def test_evaluate_function_with_null_conditional_operator_and_system_variable() -> None:
418+
# Arrange
419+
expression = "@pipeline()?.TriggeredByPipelineRunId"
420+
expression_runtime = ExpressionRuntime()
421+
state = PipelineRunState()
422+
423+
# Act
424+
evaluated_value = expression_runtime.evaluate(expression, state)
425+
426+
# Assert
427+
assert evaluated_value is None
428+
429+
371430
def test_evaluate_parameter_with_complex_object_and_array_index() -> None:
372431
# Arrange
373432
expression = "@pipeline().parameters.parameter[0].field1.field2"

0 commit comments

Comments
 (0)