Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions openfeature/provider/in_memory_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from openfeature._backports.strenum import StrEnum
from openfeature.evaluation_context import EvaluationContext
from openfeature.exception import ErrorCode
from openfeature.exception import FlagNotFoundError
from openfeature.flag_evaluation import FlagMetadata, FlagResolutionDetails, Reason
from openfeature.hook import Hook
from openfeature.provider.metadata import Metadata
Expand All @@ -26,7 +26,6 @@ class State(StrEnum):
ENABLED = "ENABLED"
DISABLED = "DISABLED"

flag_key: str
default_variant: str
variants: typing.Dict[str, T]
flag_metadata: FlagMetadata = field(default_factory=dict)
Expand Down Expand Up @@ -74,52 +73,46 @@ def resolve_boolean_details(
default_value: bool,
evaluation_context: typing.Optional[EvaluationContext] = None,
) -> FlagResolutionDetails[bool]:
return self._resolve(flag_key, default_value, evaluation_context)
return self._resolve(flag_key, evaluation_context)

def resolve_string_details(
self,
flag_key: str,
default_value: str,
evaluation_context: typing.Optional[EvaluationContext] = None,
) -> FlagResolutionDetails[str]:
return self._resolve(flag_key, default_value, evaluation_context)
return self._resolve(flag_key, evaluation_context)

def resolve_integer_details(
self,
flag_key: str,
default_value: int,
evaluation_context: typing.Optional[EvaluationContext] = None,
) -> FlagResolutionDetails[int]:
return self._resolve(flag_key, default_value, evaluation_context)
return self._resolve(flag_key, evaluation_context)

def resolve_float_details(
self,
flag_key: str,
default_value: float,
evaluation_context: typing.Optional[EvaluationContext] = None,
) -> FlagResolutionDetails[float]:
return self._resolve(flag_key, default_value, evaluation_context)
return self._resolve(flag_key, evaluation_context)

def resolve_object_details(
self,
flag_key: str,
default_value: typing.Union[dict, list],
evaluation_context: typing.Optional[EvaluationContext] = None,
) -> FlagResolutionDetails[typing.Union[dict, list]]:
return self._resolve(flag_key, default_value, evaluation_context)
return self._resolve(flag_key, evaluation_context)

def _resolve(
self,
flag_key: str,
default_value: V,
evaluation_context: typing.Optional[EvaluationContext],
) -> FlagResolutionDetails[V]:
flag = self._flags.get(flag_key)
if flag is None:
return FlagResolutionDetails(
value=default_value,
reason=Reason.ERROR,
error_code=ErrorCode.FLAG_NOT_FOUND,
error_message=f"Flag '{flag_key}' not found",
)
raise FlagNotFoundError(f"Flag '{flag_key}' not found")
return flag.resolve(evaluation_context)
7 changes: 0 additions & 7 deletions tests/features/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,30 @@ def context_func(flag: InMemoryFlag, evaluation_context: EvaluationContext):

IN_MEMORY_FLAGS = {
"boolean-flag": InMemoryFlag(
flag_key="boolean-flag",
state=InMemoryFlag.State.ENABLED,
default_variant="on",
variants={"on": True, "off": False},
context_evaluator=None,
),
"string-flag": InMemoryFlag(
flag_key="string-flag",
state=InMemoryFlag.State.ENABLED,
default_variant="greeting",
variants={"greeting": "hi", "parting": "bye"},
context_evaluator=None,
),
"integer-flag": InMemoryFlag(
flag_key="integer-flag",
state=InMemoryFlag.State.ENABLED,
default_variant="ten",
variants={"one": 1, "ten": 10},
context_evaluator=None,
),
"float-flag": InMemoryFlag(
flag_key="float-flag",
state=InMemoryFlag.State.ENABLED,
default_variant="half",
variants={"tenth": 0.1, "half": 0.5},
context_evaluator=None,
),
"object-flag": InMemoryFlag(
flag_key="object-flag",
state=InMemoryFlag.State.ENABLED,
default_variant="template",
variants={
Expand All @@ -64,14 +59,12 @@ def context_func(flag: InMemoryFlag, evaluation_context: EvaluationContext):
context_evaluator=None,
),
"context-aware": InMemoryFlag(
flag_key="context-aware",
state=InMemoryFlag.State.ENABLED,
variants={"internal": "INTERNAL", "external": "EXTERNAL"},
default_variant="external",
context_evaluator=context_func,
),
"wrong-flag": InMemoryFlag(
flag_key="wrong-flag",
state="ENABLED",
variants={"one": "uno", "two": "dos"},
default_variant="one",
Expand Down
28 changes: 9 additions & 19 deletions tests/provider/test_in_memory_provider.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from numbers import Number

from openfeature.exception import ErrorCode
from openfeature.exception import FlagNotFoundError
from openfeature.flag_evaluation import FlagResolutionDetails, Reason
from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider

Expand All @@ -19,14 +20,9 @@ def test_should_handle_unknown_flags_correctly():
# Given
provider = InMemoryProvider({})
# When
flag = provider.resolve_boolean_details(flag_key="Key", default_value=True)
with pytest.raises(FlagNotFoundError):
provider.resolve_boolean_details(flag_key="Key", default_value=True)
# Then
assert flag is not None
assert flag.value is True
assert isinstance(flag.value, bool)
assert flag.reason == Reason.ERROR
assert flag.error_code == ErrorCode.FLAG_NOT_FOUND
assert flag.error_message == "Flag 'Key' not found"


def test_calls_context_evaluator_if_present():
Expand All @@ -40,7 +36,6 @@ def context_evaluator(flag: InMemoryFlag, evaluation_context: dict):
provider = InMemoryProvider(
{
"Key": InMemoryFlag(
"Key",
"true",
{"true": True, "false": False},
context_evaluator=context_evaluator,
Expand All @@ -59,7 +54,7 @@ def context_evaluator(flag: InMemoryFlag, evaluation_context: dict):
def test_should_resolve_boolean_flag_from_in_memory():
# Given
provider = InMemoryProvider(
{"Key": InMemoryFlag("Key", "true", {"true": True, "false": False})}
{"Key": InMemoryFlag("true", {"true": True, "false": False})}
)
# When
flag = provider.resolve_boolean_details(flag_key="Key", default_value=False)
Expand All @@ -73,7 +68,7 @@ def test_should_resolve_boolean_flag_from_in_memory():
def test_should_resolve_integer_flag_from_in_memory():
# Given
provider = InMemoryProvider(
{"Key": InMemoryFlag("Key", "hundred", {"zero": 0, "hundred": 100})}
{"Key": InMemoryFlag("hundred", {"zero": 0, "hundred": 100})}
)
# When
flag = provider.resolve_integer_details(flag_key="Key", default_value=0)
Expand All @@ -87,7 +82,7 @@ def test_should_resolve_integer_flag_from_in_memory():
def test_should_resolve_float_flag_from_in_memory():
# Given
provider = InMemoryProvider(
{"Key": InMemoryFlag("Key", "ten", {"zero": 0.0, "ten": 10.23})}
{"Key": InMemoryFlag("ten", {"zero": 0.0, "ten": 10.23})}
)
# When
flag = provider.resolve_float_details(flag_key="Key", default_value=0.0)
Expand All @@ -103,7 +98,6 @@ def test_should_resolve_string_flag_from_in_memory():
provider = InMemoryProvider(
{
"Key": InMemoryFlag(
"Key",
"stringVariant",
{"defaultVariant": "Default", "stringVariant": "String"},
)
Expand All @@ -121,11 +115,7 @@ def test_should_resolve_string_flag_from_in_memory():
def test_should_resolve_list_flag_from_in_memory():
# Given
provider = InMemoryProvider(
{
"Key": InMemoryFlag(
"Key", "twoItems", {"empty": [], "twoItems": ["item1", "item2"]}
)
}
{"Key": InMemoryFlag("twoItems", {"empty": [], "twoItems": ["item1", "item2"]})}
)
# When
flag = provider.resolve_object_details(flag_key="Key", default_value=[])
Expand All @@ -144,7 +134,7 @@ def test_should_resolve_object_flag_from_in_memory():
"Boolean": True,
}
provider = InMemoryProvider(
{"Key": InMemoryFlag("Key", "obj", {"obj": return_value, "empty": {}})}
{"Key": InMemoryFlag("obj", {"obj": return_value, "empty": {}})}
)
# When
flag = provider.resolve_object_details(flag_key="Key", default_value={})
Expand Down
1 change: 0 additions & 1 deletion tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ def test_should_pass_flag_metadata_from_resolution_to_evaluation_details():
provider = InMemoryProvider(
{
"Key": InMemoryFlag(
"Key",
"true",
{"true": True, "false": False},
flag_metadata={"foo": "bar"},
Expand Down