From 5c51fe4d12adbe1c1d6f6b21113ddea5c8c468d8 Mon Sep 17 00:00:00 2001 From: Simon Schrottner Date: Sun, 17 Nov 2024 11:40:04 +0100 Subject: [PATCH] fix(flagd): object resolution for RPC and Object types (#102) Signed-off-by: Simon Schrottner --- .../contrib/provider/flagd/resolvers/grpc.py | 12 +++++-- .../tests/e2eGherkin/steps.py | 36 +++++++++---------- .../tests/test_flagd.py | 2 +- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/grpc.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/grpc.py index caab101a..194dc558 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/grpc.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/grpc.py @@ -1,6 +1,7 @@ import typing import grpc +from google.protobuf.json_format import MessageToDict from google.protobuf.struct_pb2 import Struct from openfeature.evaluation_context import EvaluationContext @@ -72,7 +73,7 @@ def resolve_object_details( ) -> FlagResolutionDetails[typing.Union[dict, list]]: return self._resolve(key, FlagType.OBJECT, default_value, evaluation_context) - def _resolve( + def _resolve( # noqa: PLR0915 self, flag_key: str, flag_type: FlagType, @@ -87,26 +88,33 @@ def _resolve( flag_key=flag_key, context=context ) response = self.stub.ResolveBoolean(request, **call_args) + value = response.value elif flag_type == FlagType.STRING: request = schema_pb2.ResolveStringRequest( # type:ignore[attr-defined] flag_key=flag_key, context=context ) response = self.stub.ResolveString(request, **call_args) + value = response.value elif flag_type == FlagType.OBJECT: request = schema_pb2.ResolveObjectRequest( # type:ignore[attr-defined] flag_key=flag_key, context=context ) response = self.stub.ResolveObject(request, **call_args) + value = MessageToDict(response, preserving_proto_field_name=True)[ + "value" + ] elif flag_type == FlagType.FLOAT: request = schema_pb2.ResolveFloatRequest( # type:ignore[attr-defined] flag_key=flag_key, context=context ) response = self.stub.ResolveFloat(request, **call_args) + value = response.value elif flag_type == FlagType.INTEGER: request = schema_pb2.ResolveIntRequest( # type:ignore[attr-defined] flag_key=flag_key, context=context ) response = self.stub.ResolveInt(request, **call_args) + value = response.value else: raise ValueError(f"Unknown flag type: {flag_type}") @@ -124,7 +132,7 @@ def _resolve( # Got a valid flag and valid type. Return it. return FlagResolutionDetails( - value=response.value, + value=value, reason=response.reason, variant=response.variant, ) diff --git a/providers/openfeature-provider-flagd/tests/e2eGherkin/steps.py b/providers/openfeature-provider-flagd/tests/e2eGherkin/steps.py index 91cd47e3..83f4602d 100644 --- a/providers/openfeature-provider-flagd/tests/e2eGherkin/steps.py +++ b/providers/openfeature-provider-flagd/tests/e2eGherkin/steps.py @@ -2,7 +2,7 @@ import typing import pytest -from asserts import assert_equal, assert_false, assert_not_equal, assert_true +from asserts import assert_equal, assert_false, assert_in, assert_not_equal, assert_true from pytest_bdd import given, parsers, then, when from tests.e2eGherkin.parsers import to_bool, to_list @@ -368,29 +368,26 @@ def assert_object( # noqa: PLR0913 ivalue: int, details: str, ) -> FlagEvaluationDetails: - # TODO: Fix this test with https://github.com/open-feature/python-sdk-contrib/issues/102 key, default = key_and_default if details: evaluation_result = client.get_object_details(key, default) - # TODO: Fix this test with https://github.com/open-feature/python-sdk-contrib/issues/102 - # assert_true(bool_field in evaluation_result.keys()) - # assert_true(string_field in evaluation_result.keys()) - # assert_true(int_field in evaluation_result.keys()) - # assert_equal(evaluation_result[bool_field], bvalue) - # assert_equal(evaluation_result[string_field], svalue) - # assert_equal(evaluation_result[int_field], ivalue) + value = evaluation_result.value + assert_in(bool_field, value) + assert_in(string_field, value) + assert_in(string_field, value) + assert_equal(value[bool_field], bvalue) + assert_equal(value[string_field], svalue) + assert_equal(value[int_field], ivalue) return evaluation_result else: evaluation_result = client.get_object_value(key, default) - # TODO: Fix this test with https://github.com/open-feature/python-sdk-contrib/issues/102 - # assert_true(bool_field in evaluation_result.keys()) - # assert_true(string_field in evaluation_result.keys()) - # assert_true(int_field in evaluation_result.keys()) - # assert_equal(evaluation_result[bool_field], bvalue) - # assert_equal(evaluation_result[string_field], svalue) - # assert_equal(evaluation_result[int_field], ivalue) + assert_in(bool_field, evaluation_result) + assert_in(string_field, evaluation_result) + assert_in(string_field, evaluation_result) + assert_equal(evaluation_result[bool_field], bvalue) + assert_equal(evaluation_result[string_field], svalue) + assert_equal(evaluation_result[int_field], ivalue) assert_not_equal(evaluation_result, None) - return FlagEvaluationDetails("no", evaluation_result) @then( @@ -404,9 +401,8 @@ def assert_for_variant_and_reason( variant: str, reason: str, ): - # TODO: Fix this test with https://github.com/open-feature/python-sdk-contrib/issues/102 - # assert_equal(evaluation_details.reason, Reason[reason]) - # assert_equal(evaluation_details.variant, variant) + assert_equal(evaluation_details.reason, Reason[reason]) + assert_equal(evaluation_details.variant, variant) assert_true(True) diff --git a/providers/openfeature-provider-flagd/tests/test_flagd.py b/providers/openfeature-provider-flagd/tests/test_flagd.py index f16210b5..bb10268a 100644 --- a/providers/openfeature-provider-flagd/tests/test_flagd.py +++ b/providers/openfeature-provider-flagd/tests/test_flagd.py @@ -65,7 +65,7 @@ def test_should_get_object_flag_from_flagd(flagd_provider_client): } # When - flag = client.get_string_details(flag_key="Key", default_value=return_value) + flag = client.get_object_details(flag_key="Key", default_value=return_value) # Then assert flag is not None