From 04a432331036cf771a613dd66dcc46c4e10d9284 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Fri, 11 Nov 2022 15:06:22 +0400 Subject: [PATCH] feat: specification-0.5.0 (#44) * feature/spec-0.3.0: Update docs on merging contexts to reflect spec Signed-off-by: Andrew Helsby * feature/spec-0.5.0: Ensure error message is optional and error code required when an error has been found Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby * feature/spec-0.5.0: Remove returns in exception docstrings Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- .../error_code.py | 0 open_feature/exception/exceptions.py | 41 +++++++++---------- .../flag_evaluation_details.py | 4 +- open_feature/open_feature_client.py | 3 +- tests/test_open_feature_api.py | 2 +- tests/test_open_feature_client.py | 2 +- tests/test_open_feature_evaluation_context.py | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) rename open_feature/{flag_evaluation => exception}/error_code.py (100%) diff --git a/open_feature/flag_evaluation/error_code.py b/open_feature/exception/error_code.py similarity index 100% rename from open_feature/flag_evaluation/error_code.py rename to open_feature/exception/error_code.py diff --git a/open_feature/exception/exceptions.py b/open_feature/exception/exceptions.py index e0e9925..a7dd87c 100644 --- a/open_feature/exception/exceptions.py +++ b/open_feature/exception/exceptions.py @@ -1,4 +1,6 @@ -from open_feature.flag_evaluation.error_code import ErrorCode +import typing + +from open_feature.exception.error_code import ErrorCode class OpenFeatureError(Exception): @@ -7,13 +9,14 @@ class OpenFeatureError(Exception): the more specific exceptions extending this one should be used. """ - def __init__(self, error_message: str = None, error_code: ErrorCode = None): + def __init__( + self, error_message: typing.Optional[str] = None, error_code: ErrorCode = None + ): """ Constructor for the generic OpenFeatureError. - @param error_message: a string message representing why the error has been - raised + @param error_message: an optional string message representing why the + error has been raised @param error_code: the ErrorCode string enum value for the type of error - @return: the generic OpenFeatureError exception """ self.error_message = error_message self.error_code = error_code @@ -25,13 +28,12 @@ class FlagNotFoundError(OpenFeatureError): key provided by the user. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str] = None): """ Constructor for the FlagNotFoundError. The error code for this type of exception is ErrorCode.FLAG_NOT_FOUND. - @param error_message: a string message representing why the error has been - raised - @return: the generic FlagNotFoundError exception + @param error_message: an optional string message representing + why the error has been raised """ super().__init__(error_message, ErrorCode.FLAG_NOT_FOUND) @@ -42,13 +44,12 @@ class GeneralError(OpenFeatureError): feature python sdk. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str] = None): """ Constructor for the GeneralError. The error code for this type of exception is ErrorCode.GENERAL. - @param error_message: a string message representing why the error has been - raised - @return: the generic GeneralError exception + @param error_message: an optional string message representing why the error + has been raised """ super().__init__(error_message, ErrorCode.GENERAL) @@ -59,13 +60,12 @@ class ParseError(OpenFeatureError): be parsed into a FlagEvaluationDetails object. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str] = None): """ Constructor for the ParseError. The error code for this type of exception is ErrorCode.PARSE_ERROR. - @param error_message: a string message representing why the error has been - raised - @return: the generic ParseError exception + @param error_message: an optional string message representing why the + error has been raised """ super().__init__(error_message, ErrorCode.PARSE_ERROR) @@ -76,13 +76,12 @@ class TypeMismatchError(OpenFeatureError): not match the type requested by the user. """ - def __init__(self, error_message: str = None): + def __init__(self, error_message: typing.Optional[str] = None): """ Constructor for the TypeMismatchError. The error code for this type of exception is ErrorCode.TYPE_MISMATCH. - @param error_message: a string message representing why the error has been - raised - @return: the generic TypeMismatchError exception + @param error_message: an optional string message representing why the + error has been raised """ super().__init__(error_message, ErrorCode.TYPE_MISMATCH) diff --git a/open_feature/flag_evaluation/flag_evaluation_details.py b/open_feature/flag_evaluation/flag_evaluation_details.py index 0caf4c0..63aa937 100644 --- a/open_feature/flag_evaluation/flag_evaluation_details.py +++ b/open_feature/flag_evaluation/flag_evaluation_details.py @@ -1,7 +1,7 @@ import typing from dataclasses import dataclass -from open_feature.flag_evaluation.error_code import ErrorCode +from open_feature.exception.error_code import ErrorCode from open_feature.flag_evaluation.reason import Reason @@ -12,4 +12,4 @@ class FlagEvaluationDetails: variant: str = None reason: Reason = None error_code: ErrorCode = None - error_message: str = None + error_message: typing.Optional[str] = None diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 259c910..af77196 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -2,12 +2,12 @@ import logging import typing from open_feature.evaluation_context.evaluation_context import EvaluationContext +from open_feature.exception.error_code import ErrorCode from open_feature.exception.exceptions import ( GeneralError, OpenFeatureError, TypeMismatchError, ) -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 @@ -248,6 +248,7 @@ class OpenFeatureClient: # https://github.com/open-feature/spec/blob/main/specification/sections/03-evaluation-context.md # Any resulting evaluation context from a before hook will overwrite # duplicate fields defined globally, on the client, or in the invocation. + # Requirement 3.2.2, 4.3.4: API.context->client.context->invocation.context invocation_context = before_hooks( flag_type, hook_context, merged_hooks, None ) diff --git a/tests/test_open_feature_api.py b/tests/test_open_feature_api.py index c3bee46..ae68714 100644 --- a/tests/test_open_feature_api.py +++ b/tests/test_open_feature_api.py @@ -1,7 +1,7 @@ import pytest +from open_feature.exception.error_code import ErrorCode from open_feature.exception.exceptions import GeneralError -from open_feature.flag_evaluation.error_code import ErrorCode from open_feature.open_feature_api import get_client, get_provider, set_provider from open_feature.provider.no_op_provider import NoOpProvider diff --git a/tests/test_open_feature_client.py b/tests/test_open_feature_client.py index c5ff42f..084d8b7 100644 --- a/tests/test_open_feature_client.py +++ b/tests/test_open_feature_client.py @@ -2,8 +2,8 @@ from unittest.mock import MagicMock import pytest +from open_feature.exception.error_code import ErrorCode from open_feature.exception.exceptions import OpenFeatureError -from open_feature.flag_evaluation.error_code import ErrorCode from open_feature.flag_evaluation.reason import Reason from open_feature.hooks.hook import Hook diff --git a/tests/test_open_feature_evaluation_context.py b/tests/test_open_feature_evaluation_context.py index fc353d9..41539a6 100644 --- a/tests/test_open_feature_evaluation_context.py +++ b/tests/test_open_feature_evaluation_context.py @@ -1,8 +1,8 @@ import pytest from open_feature.evaluation_context.evaluation_context import EvaluationContext +from open_feature.exception.error_code import ErrorCode from open_feature.exception.exceptions import GeneralError -from open_feature.flag_evaluation.error_code import ErrorCode from open_feature.open_feature_evaluation_context import ( api_evaluation_context, set_api_evaluation_context,