feat: pass flag_metadata from resolution to evaluation details (#212)

Signed-off-by: Federico Bond <federicobond@gmail.com>
This commit is contained in:
Federico Bond 2023-10-18 11:36:30 -03:00 committed by GitHub
parent d41cea270e
commit 88a204dc27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 5 deletions

View File

@ -377,6 +377,7 @@ class OpenFeatureClient:
flag_key=flag_key,
value=resolution.value,
variant=resolution.variant,
flag_metadata=resolution.flag_metadata or {},
reason=resolution.reason,
error_code=resolution.error_code,
error_message=resolution.error_message,

View File

@ -29,6 +29,8 @@ class Reason(StrEnum):
UNKNOWN = "UNKNOWN"
FlagMetadata = typing.Mapping[str, typing.Any]
T = typing.TypeVar("T", covariant=True)
@ -37,6 +39,7 @@ class FlagEvaluationDetails(typing.Generic[T]):
flag_key: str
value: T
variant: typing.Optional[str] = None
flag_metadata: FlagMetadata = field(default_factory=dict)
reason: typing.Optional[Reason] = None
error_code: typing.Optional[ErrorCode] = None
error_message: typing.Optional[str] = None
@ -58,4 +61,4 @@ class FlagResolutionDetails(typing.Generic[U]):
error_message: typing.Optional[str] = None
reason: typing.Optional[Reason] = None
variant: typing.Optional[str] = None
flag_metadata: typing.Optional[str] = None
flag_metadata: FlagMetadata = field(default_factory=dict)

View File

@ -1,10 +1,10 @@
import typing
from dataclasses import dataclass
from dataclasses import dataclass, field
from openfeature._backports.strenum import StrEnum
from openfeature.evaluation_context import EvaluationContext
from openfeature.exception import ErrorCode
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
from openfeature.flag_evaluation import FlagMetadata, FlagResolutionDetails, Reason
from openfeature.hook import Hook
from openfeature.provider.metadata import Metadata
from openfeature.provider.provider import AbstractProvider
@ -29,6 +29,7 @@ class InMemoryFlag(typing.Generic[T]):
flag_key: str
default_variant: str
variants: typing.Dict[str, T]
flag_metadata: FlagMetadata = field(default_factory=dict)
state: State = State.ENABLED
context_evaluator: typing.Optional[
typing.Callable[["InMemoryFlag", EvaluationContext], FlagResolutionDetails[T]]
@ -46,6 +47,7 @@ class InMemoryFlag(typing.Generic[T]):
value=self.variants[self.default_variant],
reason=Reason.STATIC,
variant=self.default_variant,
flag_metadata=self.flag_metadata,
)

View File

@ -7,6 +7,7 @@ from openfeature.client import OpenFeatureClient
from openfeature.exception import ErrorCode, OpenFeatureError
from openfeature.flag_evaluation import Reason
from openfeature.hook import Hook
from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider
from openfeature.provider.no_op_provider import NoOpProvider
@ -97,6 +98,28 @@ def test_should_raise_exception_when_invalid_flag_type_provided(no_op_provider_c
assert flag.reason == Reason.ERROR
def test_should_pass_flag_metadata_from_resolution_to_evaluation_details():
# Given
provider = InMemoryProvider(
{
"Key": InMemoryFlag(
"Key",
"true",
{"true": True, "false": False},
flag_metadata={"foo": "bar"},
)
}
)
client = OpenFeatureClient("my-client", None, provider)
# When
details = client.get_boolean_details(flag_key="Key", default_value=False)
# Then
assert details is not None
assert details.flag_metadata == {"foo": "bar"}
def test_should_handle_a_generic_exception_thrown_by_a_provider(no_op_provider_client):
# Given
exception_hook = MagicMock(spec=Hook)

View File

@ -2,11 +2,12 @@ from openfeature.exception import ErrorCode
from openfeature.flag_evaluation import FlagEvaluationDetails, Reason
def test_evaulation_details_reason_should_be_a_string():
def test_evaluation_details_reason_should_be_a_string():
# Given
flag_key = "my-flag"
flag_value = 100
variant = "1-hundred"
flag_metadata = {}
reason = Reason.DEFAULT
error_code = ErrorCode.GENERAL
error_message = "message"
@ -16,6 +17,7 @@ def test_evaulation_details_reason_should_be_a_string():
flag_key,
flag_value,
variant,
flag_metadata,
reason,
error_code,
error_message,
@ -30,7 +32,7 @@ def test_evaulation_details_reason_should_be_a_string():
assert reason == flag_details.reason
def test_evaulation_details_reason_should_be_a_string_when_set():
def test_evaluation_details_reason_should_be_a_string_when_set():
# Given
flag_key = "my-flag"
flag_value = 100