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
23 changes: 10 additions & 13 deletions open_feature/flag_evaluation/flag_evaluation_details.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import typing
from dataclasses import dataclass

from open_feature.flag_evaluation.error_code import ErrorCode
from open_feature.flag_evaluation.reason import Reason


@dataclass
class FlagEvaluationDetails:
def __init__(
self,
key: str,
value,
reason: Reason,
error_code: ErrorCode = None,
variant=None,
):
self.key = key
self.value = value
self.reason = reason
self.error_code = error_code
self.variant = variant
flag_key: str
value: typing.Any
variant: str = None
reason: Reason = None
error_code: ErrorCode = None
error_message: str = None
58 changes: 35 additions & 23 deletions open_feature/open_feature_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from open_feature.evaluation_context.evaluation_context import EvaluationContext
from open_feature.exception.exceptions import GeneralError
from open_feature.flag_evaluation.error_code import ErrorCode
from open_feature.flag_evaluation.flag_evaluation_details import FlagEvaluationDetails
from open_feature.flag_evaluation.flag_type import FlagType
from open_feature.flag_evaluation.reason import Reason
Expand Down Expand Up @@ -40,119 +41,119 @@ def add_hooks(self, hooks: typing.List[Hook]):

def get_boolean_value(
self,
key: str,
flag_key: str,
default_value: bool,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> bool:
return self.evaluate_flag_details(
FlagType.BOOLEAN,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
).value

def get_boolean_details(
self,
key: str,
flag_key: str,
default_value: bool,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> FlagEvaluationDetails:
return self.evaluate_flag_details(
FlagType.BOOLEAN,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
)

def get_string_value(
self,
key: str,
flag_key: str,
default_value: str,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> str:
return self.evaluate_flag_details(
FlagType.STRING,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
).value

def get_string_details(
self,
key: str,
flag_key: str,
default_value: str,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> FlagEvaluationDetails:
return self.evaluate_flag_details(
FlagType.STRING,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
)

def get_number_value(
self,
key: str,
flag_key: str,
default_value: Number,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> Number:
return self.evaluate_flag_details(
FlagType.NUMBER,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
).value

def get_number_details(
self,
key: str,
flag_key: str,
default_value: Number,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> FlagEvaluationDetails:
return self.evaluate_flag_details(
FlagType.NUMBER,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
)

def get_object_value(
self,
key: str,
flag_key: str,
default_value: dict,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> dict:
return self.evaluate_flag_details(
FlagType.OBJECT,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
).value

def get_object_details(
self,
key: str,
flag_key: str,
default_value: dict,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
) -> FlagEvaluationDetails:
return self.evaluate_flag_details(
FlagType.OBJECT,
key,
flag_key,
default_value,
evaluation_context,
flag_evaluation_options,
Expand All @@ -161,7 +162,7 @@ def get_object_details(
def evaluate_flag_details(
self,
flag_type: FlagType,
key: str,
flag_key: str,
default_value: typing.Any,
evaluation_context: EvaluationContext = None,
flag_evaluation_options: typing.Any = None,
Expand All @@ -182,7 +183,7 @@ def evaluate_flag_details(
evaluation_context = EvaluationContext()

hook_context = HookContext(
flag_key=key,
flag_key=flag_key,
flag_type=flag_type,
default_value=default_value,
evaluation_context=evaluation_context,
Expand All @@ -207,7 +208,7 @@ def evaluate_flag_details(

flag_evaluation = self.create_provider_evaluation(
flag_type,
key,
flag_key,
default_value,
merged_context,
)
Expand All @@ -216,15 +217,26 @@ def evaluate_flag_details(

return flag_evaluation

except OpenFeatureError as e: # noqa
error_hooks(flag_type, hook_context, e, merged_hooks, None)
return FlagEvaluationDetails(
flag_key=flag_key,
value=default_value,
reason=Reason.ERROR,
error_code=e.error_code,
error_message=e.error_message,
)
# Catch any type of exception here since the user can provide any exception
# in the error hooks
except Exception as e: # noqa
error_hooks(flag_type, hook_context, e, merged_hooks, None)
error_message = getattr(e, "error_message", str(e))
return FlagEvaluationDetails(
key=key,
flag_key=flag_key,
value=default_value,
reason=Reason.ERROR,
error_code=e.error_message,
error_code=ErrorCode.GENERAL,
error_message=error_message,
)

finally:
Expand All @@ -233,7 +245,7 @@ def evaluate_flag_details(
def create_provider_evaluation(
self,
flag_type: FlagType,
key: str,
flag_key: str,
default_value: typing.Any,
evaluation_context: EvaluationContext = None,
) -> FlagEvaluationDetails:
Expand All @@ -248,7 +260,7 @@ def create_provider_evaluation(
provider
"""
args = (
key,
flag_key,
default_value,
evaluation_context,
)
Expand Down
16 changes: 8 additions & 8 deletions open_feature/provider/no_op_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,51 @@ def get_name(self) -> str:

def get_boolean_details(
self,
key: str,
flag_key: str,
default_value: bool,
evaluation_context: EvaluationContext = None,
):
return FlagEvaluationDetails(
key=key,
flag_key=flag_key,
value=default_value,
reason=Reason.DEFAULT,
variant=PASSED_IN_DEFAULT,
)

def get_string_details(
self,
key: str,
flag_key: str,
default_value: str,
evaluation_context: EvaluationContext = None,
):
return FlagEvaluationDetails(
key=key,
flag_key=flag_key,
value=default_value,
reason=Reason.DEFAULT,
variant=PASSED_IN_DEFAULT,
)

def get_number_details(
self,
key: str,
flag_key: str,
default_value: Number,
evaluation_context: EvaluationContext = None,
):
return FlagEvaluationDetails(
key=key,
flag_key=flag_key,
value=default_value,
reason=Reason.DEFAULT,
variant=PASSED_IN_DEFAULT,
)

def get_object_details(
self,
key: str,
flag_key: str,
default_value: dict,
evaluation_context: EvaluationContext = None,
):
return FlagEvaluationDetails(
key=key,
flag_key=flag_key,
value=default_value,
reason=Reason.DEFAULT,
variant=PASSED_IN_DEFAULT,
Expand Down
8 changes: 4 additions & 4 deletions open_feature/provider/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def get_name(self) -> str:
@abstractmethod
def get_boolean_details(
self,
key: str,
flag_key: str,
default_value: bool,
evaluation_context: EvaluationContext = EvaluationContext(),
):
Expand All @@ -21,7 +21,7 @@ def get_boolean_details(
@abstractmethod
def get_string_details(
self,
key: str,
flag_key: str,
default_value: str,
evaluation_context: EvaluationContext = EvaluationContext(),
):
Expand All @@ -30,7 +30,7 @@ def get_string_details(
@abstractmethod
def get_number_details(
self,
key: str,
flag_key: str,
default_value: Number,
evaluation_context: EvaluationContext = EvaluationContext(),
):
Expand All @@ -39,7 +39,7 @@ def get_number_details(
@abstractmethod
def get_object_details(
self,
key: str,
flag_key: str,
default_value: dict,
evaluation_context: EvaluationContext = EvaluationContext(),
):
Expand Down
10 changes: 6 additions & 4 deletions tests/provider/test_no_op_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def setup():
def test_should_get_boolean_flag_from_no_op(no_op_provider_client):
# Given
# When
flag = no_op_provider_client.get_boolean_details(key="Key", default_value=True)
flag = no_op_provider_client.get_boolean_details(flag_key="Key", default_value=True)
# Then
assert flag is not None
assert flag.value
Expand All @@ -23,7 +23,7 @@ def test_should_get_boolean_flag_from_no_op(no_op_provider_client):
def test_should_get_number_flag_from_no_op(no_op_provider_client):
# Given
# When
flag = no_op_provider_client.get_number_details(key="Key", default_value=100)
flag = no_op_provider_client.get_number_details(flag_key="Key", default_value=100)
# Then
assert flag is not None
assert flag.value == 100
Expand All @@ -33,7 +33,9 @@ def test_should_get_number_flag_from_no_op(no_op_provider_client):
def test_should_get_string_flag_from_no_op(no_op_provider_client):
# Given
# When
flag = no_op_provider_client.get_string_details(key="Key", default_value="String")
flag = no_op_provider_client.get_string_details(
flag_key="Key", default_value="String"
)
# Then
assert flag is not None
assert flag.value == "String"
Expand All @@ -49,7 +51,7 @@ def test_should_get_object_flag_from_no_op(no_op_provider_client):
}
# When
flag = no_op_provider_client.get_string_details(
key="Key", default_value=return_value
flag_key="Key", default_value=return_value
)
# Then
assert flag is not None
Expand Down