From 508caee28a67682a37f0b1cbb041f3c929535686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Mon, 17 Oct 2022 11:57:36 -0600 Subject: [PATCH 1/6] Fix type checking within client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- open_feature/hooks/hook_context.py | 4 ++-- open_feature/hooks/hook_support.py | 8 ++++---- open_feature/open_feature_client.py | 5 +++++ open_feature/provider/no_op_provider.py | 6 +++--- open_feature/provider/provider.py | 8 +++++--- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/open_feature/hooks/hook_context.py b/open_feature/hooks/hook_context.py index 13b90c40..7969a050 100644 --- a/open_feature/hooks/hook_context.py +++ b/open_feature/hooks/hook_context.py @@ -11,5 +11,5 @@ class HookContext: flag_type: FlagType default_value: typing.Any evaluation_context: EvaluationContext - client_metadata: dict = None - provider_metadata: dict = None + client_metadata: typing.Optional[dict] = None + provider_metadata: typing.Optional[dict] = None diff --git a/open_feature/hooks/hook_support.py b/open_feature/hooks/hook_support.py index 11115044..21a65b87 100644 --- a/open_feature/hooks/hook_support.py +++ b/open_feature/hooks/hook_support.py @@ -15,7 +15,7 @@ def error_hooks( hook_context: HookContext, exception: Exception, hooks: typing.List[Hook], - hints: dict, + hints: dict = None, ): kwargs = {"hook_context": hook_context, "exception": exception, "hints": hints} _execute_hooks( @@ -27,7 +27,7 @@ def after_all_hooks( flag_type: FlagType, hook_context: HookContext, hooks: typing.List[Hook], - hints: dict, + hints: typing.Optional[typing.Mapping], ): kwargs = {"hook_context": hook_context, "hints": hints} _execute_hooks( @@ -40,7 +40,7 @@ def after_hooks( hook_context: HookContext, details: FlagEvaluationDetails, hooks: typing.List[Hook], - hints: dict, + hints: typing.Optional[typing.Mapping], ): kwargs = {"hook_context": hook_context, "details": details, "hints": hints} _execute_hooks_unchecked( @@ -52,7 +52,7 @@ def before_hooks( flag_type: FlagType, hook_context: HookContext, hooks: typing.List[Hook], - hints: dict, + hints: typing.Optional[dict], ) -> EvaluationContext: kwargs = {"hook_context": hook_context, "hints": hints} executed_hooks = _execute_hooks_unchecked( diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index af771968..fd797219 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -25,6 +25,9 @@ from open_feature.provider.provider import AbstractProvider NUMERIC_TYPES = [FlagType.FLOAT, FlagType.INTEGER] +GetDetailsCallable = typing.Callable[ + [str, typing.Any, typing.Optional[EvaluationContext]], FlagEvaluationDetails +] class OpenFeatureClient: @@ -332,6 +335,8 @@ def _create_provider_evaluation( FlagType.STRING: self.provider.resolve_string_details, }.get(flag_type) + get_details_callable = get_details_callables.get(flag_type) + if not get_details_callable: raise GeneralError(error_message="Unknown flag type") diff --git a/open_feature/provider/no_op_provider.py b/open_feature/provider/no_op_provider.py index f3bdda4a..847a4cb2 100644 --- a/open_feature/provider/no_op_provider.py +++ b/open_feature/provider/no_op_provider.py @@ -22,7 +22,7 @@ def resolve_boolean_details( self, flag_key: str, default_value: bool, - evaluation_context: EvaluationContext = None, + evaluation_context: Optional[EvaluationContext] = None, ): return FlagEvaluationDetails( flag_key=flag_key, @@ -35,7 +35,7 @@ def resolve_string_details( self, flag_key: str, default_value: str, - evaluation_context: EvaluationContext = None, + evaluation_context: Optional[EvaluationContext] = None, ): return FlagEvaluationDetails( flag_key=flag_key, @@ -74,7 +74,7 @@ def resolve_object_details( self, flag_key: str, default_value: dict, - evaluation_context: EvaluationContext = None, + evaluation_context: Optional[EvaluationContext] = None, ): return FlagEvaluationDetails( flag_key=flag_key, diff --git a/open_feature/provider/provider.py b/open_feature/provider/provider.py index b755374f..ecaafd82 100644 --- a/open_feature/provider/provider.py +++ b/open_feature/provider/provider.py @@ -1,5 +1,7 @@ import typing from abc import abstractmethod +from numbers import Number +from typing import Optional from open_feature.evaluation_context.evaluation_context import EvaluationContext from open_feature.hooks.hook import Hook @@ -20,7 +22,7 @@ def resolve_boolean_details( self, flag_key: str, default_value: bool, - evaluation_context: EvaluationContext = EvaluationContext(), + evaluation_context: Optional[EvaluationContext] = None, ): pass @@ -29,7 +31,7 @@ def resolve_string_details( self, flag_key: str, default_value: str, - evaluation_context: EvaluationContext = EvaluationContext(), + evaluation_context: Optional[EvaluationContext] = None, ): pass @@ -56,6 +58,6 @@ def resolve_object_details( self, flag_key: str, default_value: dict, - evaluation_context: EvaluationContext = EvaluationContext(), + evaluation_context: Optional[EvaluationContext] = None, ): pass From 7d9cbe612fd6eaffecdd474d11e36dbd917c6e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Wed, 19 Oct 2022 15:55:10 -0600 Subject: [PATCH 2/6] Make linter happy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- open_feature/open_feature_client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index fd797219..8b1313bf 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -8,6 +8,8 @@ OpenFeatureError, TypeMismatchError, ) +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_evaluation_options import FlagEvaluationOptions from open_feature.flag_evaluation.flag_type import FlagType From 9c69595af097b50521c69d6e4ad07c4bd4895219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Wed, 19 Oct 2022 16:01:25 -0600 Subject: [PATCH 3/6] Migrate Hook Hints to Mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- open_feature/hooks/hook_support.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/open_feature/hooks/hook_support.py b/open_feature/hooks/hook_support.py index 21a65b87..db6ff975 100644 --- a/open_feature/hooks/hook_support.py +++ b/open_feature/hooks/hook_support.py @@ -15,7 +15,7 @@ def error_hooks( hook_context: HookContext, exception: Exception, hooks: typing.List[Hook], - hints: dict = None, + hints: typing.Optional[typing.Mapping] = None, ): kwargs = {"hook_context": hook_context, "exception": exception, "hints": hints} _execute_hooks( @@ -27,7 +27,7 @@ def after_all_hooks( flag_type: FlagType, hook_context: HookContext, hooks: typing.List[Hook], - hints: typing.Optional[typing.Mapping], + hints: typing.Optional[typing.Mapping] = None, ): kwargs = {"hook_context": hook_context, "hints": hints} _execute_hooks( @@ -40,7 +40,7 @@ def after_hooks( hook_context: HookContext, details: FlagEvaluationDetails, hooks: typing.List[Hook], - hints: typing.Optional[typing.Mapping], + hints: typing.Optional[typing.Mapping] = None, ): kwargs = {"hook_context": hook_context, "details": details, "hints": hints} _execute_hooks_unchecked( From f5ee4b06b6e917d52b1df8c709ad5459387074d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Wed, 19 Oct 2022 16:01:54 -0600 Subject: [PATCH 4/6] Fix type annotations in FlagEvaluationDetails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- open_feature/flag_evaluation/flag_evaluation_details.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/open_feature/flag_evaluation/flag_evaluation_details.py b/open_feature/flag_evaluation/flag_evaluation_details.py index 63aa937f..ca85e8b5 100644 --- a/open_feature/flag_evaluation/flag_evaluation_details.py +++ b/open_feature/flag_evaluation/flag_evaluation_details.py @@ -9,7 +9,7 @@ class FlagEvaluationDetails: flag_key: str value: typing.Any - variant: str = None - reason: Reason = None - error_code: ErrorCode = None + variant: typing.Optional[str] = None + reason: typing.Optional[Reason] = None + error_code: typing.Optional[ErrorCode] = None error_message: typing.Optional[str] = None From 860d42d11d0e4f7b9cdee70bfa820b5fb2f7fd65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Wed, 19 Oct 2022 16:04:45 -0600 Subject: [PATCH 5/6] Fix last hint typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- open_feature/hooks/hook_support.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open_feature/hooks/hook_support.py b/open_feature/hooks/hook_support.py index db6ff975..039afe7b 100644 --- a/open_feature/hooks/hook_support.py +++ b/open_feature/hooks/hook_support.py @@ -52,7 +52,7 @@ def before_hooks( flag_type: FlagType, hook_context: HookContext, hooks: typing.List[Hook], - hints: typing.Optional[dict], + hints: typing.Optional[typing.Mapping] = None, ) -> EvaluationContext: kwargs = {"hook_context": hook_context, "hints": hints} executed_hooks = _execute_hooks_unchecked( From 7102813a0f05c815f5fc19ed235288ee470397f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Fri, 11 Nov 2022 19:09:41 -0700 Subject: [PATCH 6/6] Rework typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Schönlaub --- .../evaluation_context/evaluation_context.py | 9 +- open_feature/exception/exceptions.py | 18 ++-- .../flag_evaluation_details.py | 6 +- open_feature/open_feature_api.py | 6 +- open_feature/open_feature_client.py | 83 +++++++++++-------- open_feature/provider/no_op_provider.py | 20 ++--- open_feature/provider/provider.py | 23 +++-- tests/test_open_feature_client.py | 2 +- 8 files changed, 94 insertions(+), 73 deletions(-) diff --git a/open_feature/evaluation_context/evaluation_context.py b/open_feature/evaluation_context/evaluation_context.py index cab69762..64edf6d1 100644 --- a/open_feature/evaluation_context/evaluation_context.py +++ b/open_feature/evaluation_context/evaluation_context.py @@ -1,5 +1,12 @@ +import typing + + class EvaluationContext: - def __init__(self, targeting_key: str = None, attributes: dict = None): + def __init__( + self, + targeting_key: typing.Optional[str] = None, + attributes: typing.Optional[dict] = None, + ): self.targeting_key = targeting_key self.attributes = attributes or {} diff --git a/open_feature/exception/exceptions.py b/open_feature/exception/exceptions.py index a7dd87cc..bfab67b4 100644 --- a/open_feature/exception/exceptions.py +++ b/open_feature/exception/exceptions.py @@ -10,7 +10,7 @@ class OpenFeatureError(Exception): """ def __init__( - self, error_message: typing.Optional[str] = None, error_code: ErrorCode = None + self, error_code: ErrorCode, error_message: typing.Optional[str] = None ): """ Constructor for the generic OpenFeatureError. @@ -35,7 +35,7 @@ def __init__(self, error_message: typing.Optional[str] = None): @param error_message: an optional string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.FLAG_NOT_FOUND) + super().__init__(ErrorCode.FLAG_NOT_FOUND, error_message) class GeneralError(OpenFeatureError): @@ -51,7 +51,7 @@ def __init__(self, error_message: typing.Optional[str] = None): @param error_message: an optional string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.GENERAL) + super().__init__(ErrorCode.GENERAL, error_message) class ParseError(OpenFeatureError): @@ -67,7 +67,7 @@ def __init__(self, error_message: typing.Optional[str] = None): @param error_message: an optional string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.PARSE_ERROR) + super().__init__(ErrorCode.PARSE_ERROR, error_message) class TypeMismatchError(OpenFeatureError): @@ -83,7 +83,7 @@ def __init__(self, error_message: typing.Optional[str] = None): @param error_message: an optional string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.TYPE_MISMATCH) + super().__init__(ErrorCode.TYPE_MISMATCH, error_message) class TargetingKeyMissingError(OpenFeatureError): @@ -92,14 +92,14 @@ class TargetingKeyMissingError(OpenFeatureError): but one was not provided in the evaluation context. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str] = None): """ Constructor for the TargetingKeyMissingError. The error code for this type of exception is ErrorCode.TARGETING_KEY_MISSING. @param error_message: a string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.TARGETING_KEY_MISSING) + super().__init__(ErrorCode.TARGETING_KEY_MISSING, error_message) class InvalidContextError(OpenFeatureError): @@ -108,11 +108,11 @@ class InvalidContextError(OpenFeatureError): requirements. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str]): """ Constructor for the InvalidContextError. The error code for this type of exception is ErrorCode.INVALID_CONTEXT. @param error_message: a string message representing why the error has been raised """ - super().__init__(error_message, ErrorCode.INVALID_CONTEXT) + super().__init__(ErrorCode.INVALID_CONTEXT, error_message) diff --git a/open_feature/flag_evaluation/flag_evaluation_details.py b/open_feature/flag_evaluation/flag_evaluation_details.py index ca85e8b5..2bf9fceb 100644 --- a/open_feature/flag_evaluation/flag_evaluation_details.py +++ b/open_feature/flag_evaluation/flag_evaluation_details.py @@ -4,11 +4,13 @@ from open_feature.exception.error_code import ErrorCode from open_feature.flag_evaluation.reason import Reason +T = typing.TypeVar("T", covariant=True) + @dataclass -class FlagEvaluationDetails: +class FlagEvaluationDetails(typing.Generic[T]): flag_key: str - value: typing.Any + value: T variant: typing.Optional[str] = None reason: typing.Optional[Reason] = None error_code: typing.Optional[ErrorCode] = None diff --git a/open_feature/open_feature_api.py b/open_feature/open_feature_api.py index 60c3f3d2..7a4c9f5d 100644 --- a/open_feature/open_feature_api.py +++ b/open_feature/open_feature_api.py @@ -4,10 +4,12 @@ from open_feature.open_feature_client import OpenFeatureClient from open_feature.provider.provider import AbstractProvider -_provider = None +_provider: typing.Optional[AbstractProvider] = None -def get_client(name: str = None, version: str = None) -> OpenFeatureClient: +def get_client( + name: typing.Optional[str] = None, version: typing.Optional[str] = None +) -> OpenFeatureClient: if _provider is None: raise GeneralError( error_message="Provider not set. Call set_provider before using get_client" diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 8b1313bf..e56f8752 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -8,8 +8,6 @@ OpenFeatureError, TypeMismatchError, ) -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_evaluation_options import FlagEvaluationOptions from open_feature.flag_evaluation.flag_type import FlagType @@ -26,20 +24,34 @@ from open_feature.provider.no_op_provider import NoOpProvider from open_feature.provider.provider import AbstractProvider -NUMERIC_TYPES = [FlagType.FLOAT, FlagType.INTEGER] -GetDetailsCallable = typing.Callable[ - [str, typing.Any, typing.Optional[EvaluationContext]], FlagEvaluationDetails + +GetDetailCallable = typing.Union[ + typing.Callable[ + [str, bool, typing.Optional[EvaluationContext]], FlagEvaluationDetails[bool] + ], + typing.Callable[ + [str, int, typing.Optional[EvaluationContext]], FlagEvaluationDetails[int] + ], + typing.Callable[ + [str, float, typing.Optional[EvaluationContext]], FlagEvaluationDetails[float] + ], + typing.Callable[ + [str, str, typing.Optional[EvaluationContext]], FlagEvaluationDetails[str] + ], + typing.Callable[ + [str, dict, typing.Optional[EvaluationContext]], FlagEvaluationDetails[dict] + ], ] class OpenFeatureClient: def __init__( self, - name: str, - version: str, - context: EvaluationContext = None, - hooks: typing.List[Hook] = None, - provider: AbstractProvider = None, + name: typing.Optional[str], + version: typing.Optional[str], + provider: AbstractProvider, + context: typing.Optional[EvaluationContext] = None, + hooks: typing.Optional[typing.List[Hook]] = None, ): self.name = name self.version = version @@ -54,8 +66,8 @@ def get_boolean_value( self, flag_key: str, default_value: bool, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> bool: return self.evaluate_flag_details( FlagType.BOOLEAN, @@ -69,8 +81,8 @@ def get_boolean_details( self, flag_key: str, default_value: bool, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.BOOLEAN, @@ -84,8 +96,8 @@ def get_string_value( self, flag_key: str, default_value: str, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> str: return self.evaluate_flag_details( FlagType.STRING, @@ -99,8 +111,8 @@ def get_string_details( self, flag_key: str, default_value: str, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.STRING, @@ -114,8 +126,8 @@ def get_integer_value( self, flag_key: str, default_value: int, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> int: return self.get_integer_details( flag_key, @@ -128,8 +140,8 @@ def get_integer_details( self, flag_key: str, default_value: int, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.INTEGER, @@ -143,8 +155,8 @@ def get_float_value( self, flag_key: str, default_value: float, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> float: return self.get_float_details( flag_key, @@ -157,8 +169,8 @@ def get_float_details( self, flag_key: str, default_value: float, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.FLOAT, @@ -172,8 +184,8 @@ def get_object_value( self, flag_key: str, default_value: dict, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> dict: return self.evaluate_flag_details( FlagType.OBJECT, @@ -187,8 +199,8 @@ def get_object_details( self, flag_key: str, default_value: dict, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.OBJECT, @@ -203,8 +215,8 @@ def evaluate_flag_details( flag_type: FlagType, flag_key: str, default_value: typing.Any, - evaluation_context: EvaluationContext = None, - flag_evaluation_options: FlagEvaluationOptions = None, + evaluation_context: typing.Optional[EvaluationContext] = None, + flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None, ) -> FlagEvaluationDetails: """ Evaluate the flag requested by the user from the clients provider. @@ -307,7 +319,7 @@ def _create_provider_evaluation( flag_type: FlagType, flag_key: str, default_value: typing.Any, - evaluation_context: EvaluationContext = None, + evaluation_context: typing.Optional[EvaluationContext] = None, ) -> FlagEvaluationDetails: """ Encapsulated method to create a FlagEvaluationDetail from a specific provider. @@ -329,16 +341,15 @@ def _create_provider_evaluation( logging.info("No provider configured, using no-op provider.") self.provider = NoOpProvider() - get_details_callable = { + get_details_callables: typing.Mapping[FlagType, GetDetailCallable] = { FlagType.BOOLEAN: self.provider.resolve_boolean_details, FlagType.INTEGER: self.provider.resolve_integer_details, FlagType.FLOAT: self.provider.resolve_float_details, FlagType.OBJECT: self.provider.resolve_object_details, FlagType.STRING: self.provider.resolve_string_details, - }.get(flag_type) + } get_details_callable = get_details_callables.get(flag_type) - if not get_details_callable: raise GeneralError(error_message="Unknown flag type") diff --git a/open_feature/provider/no_op_provider.py b/open_feature/provider/no_op_provider.py index 847a4cb2..14b7dac5 100644 --- a/open_feature/provider/no_op_provider.py +++ b/open_feature/provider/no_op_provider.py @@ -22,8 +22,8 @@ def resolve_boolean_details( self, flag_key: str, default_value: bool, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[bool]: return FlagEvaluationDetails( flag_key=flag_key, value=default_value, @@ -35,8 +35,8 @@ def resolve_string_details( self, flag_key: str, default_value: str, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[str]: return FlagEvaluationDetails( flag_key=flag_key, value=default_value, @@ -48,8 +48,8 @@ def resolve_integer_details( self, flag_key: str, default_value: int, - evaluation_context: EvaluationContext = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[int]: return FlagEvaluationDetails( flag_key=flag_key, value=default_value, @@ -61,8 +61,8 @@ def resolve_float_details( self, flag_key: str, default_value: float, - evaluation_context: EvaluationContext = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[float]: return FlagEvaluationDetails( flag_key=flag_key, value=default_value, @@ -74,8 +74,8 @@ def resolve_object_details( self, flag_key: str, default_value: dict, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[dict]: return FlagEvaluationDetails( flag_key=flag_key, value=default_value, diff --git a/open_feature/provider/provider.py b/open_feature/provider/provider.py index ecaafd82..5b01a499 100644 --- a/open_feature/provider/provider.py +++ b/open_feature/provider/provider.py @@ -1,9 +1,8 @@ import typing from abc import abstractmethod -from numbers import Number -from typing import Optional from open_feature.evaluation_context.evaluation_context import EvaluationContext +from open_feature.flag_evaluation.flag_evaluation_details import FlagEvaluationDetails from open_feature.hooks.hook import Hook from open_feature.provider.metadata import Metadata @@ -22,8 +21,8 @@ def resolve_boolean_details( self, flag_key: str, default_value: bool, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[bool]: pass @abstractmethod @@ -31,8 +30,8 @@ def resolve_string_details( self, flag_key: str, default_value: str, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[str]: pass @abstractmethod @@ -40,8 +39,8 @@ def resolve_integer_details( self, flag_key: str, default_value: int, - evaluation_context: EvaluationContext = EvaluationContext(), - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[int]: pass @abstractmethod @@ -49,8 +48,8 @@ def resolve_float_details( self, flag_key: str, default_value: float, - evaluation_context: EvaluationContext = EvaluationContext(), - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[float]: pass @abstractmethod @@ -58,6 +57,6 @@ def resolve_object_details( self, flag_key: str, default_value: dict, - evaluation_context: Optional[EvaluationContext] = None, - ): + evaluation_context: typing.Optional[EvaluationContext] = None, + ) -> FlagEvaluationDetails[dict]: pass diff --git a/tests/test_open_feature_client.py b/tests/test_open_feature_client.py index 084d8b7d..2c539e96 100644 --- a/tests/test_open_feature_client.py +++ b/tests/test_open_feature_client.py @@ -108,7 +108,7 @@ def test_should_handle_an_open_feature_exception_thrown_by_a_provider( # Given exception_hook = MagicMock(spec=Hook) exception_hook.after.side_effect = OpenFeatureError( - "error_message", ErrorCode.GENERAL + ErrorCode.GENERAL, "error_message" ) no_op_provider_client.add_hooks([exception_hook])