Skip to content

Commit f95b27a

Browse files
authored
refactor: refine typing.Any type hints (#504)
* refine typing.Any type hints Signed-off-by: gruebel <[email protected]> * exclude TYPE_CHECKING from coverage Signed-off-by: gruebel <[email protected]> --------- Signed-off-by: gruebel <[email protected]>
1 parent 87e4485 commit f95b27a

File tree

9 files changed

+259
-49
lines changed

9 files changed

+259
-49
lines changed

openfeature/client.py

Lines changed: 151 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
import typing
3-
from collections.abc import Awaitable
3+
from collections.abc import Awaitable, Sequence
44
from dataclasses import dataclass
55

66
from openfeature import _event_support
@@ -19,6 +19,7 @@
1919
FlagEvaluationOptions,
2020
FlagResolutionDetails,
2121
FlagType,
22+
FlagValueType,
2223
Reason,
2324
)
2425
from openfeature.hook import Hook, HookContext, HookHints, get_hooks
@@ -342,10 +343,12 @@ async def get_float_details_async(
342343
def get_object_value(
343344
self,
344345
flag_key: str,
345-
default_value: typing.Union[dict, list],
346+
default_value: typing.Union[
347+
Sequence[FlagValueType], typing.Mapping[str, FlagValueType]
348+
],
346349
evaluation_context: typing.Optional[EvaluationContext] = None,
347350
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
348-
) -> typing.Union[dict, list]:
351+
) -> typing.Union[Sequence[FlagValueType], typing.Mapping[str, FlagValueType]]:
349352
return self.get_object_details(
350353
flag_key,
351354
default_value,
@@ -356,10 +359,12 @@ def get_object_value(
356359
async def get_object_value_async(
357360
self,
358361
flag_key: str,
359-
default_value: typing.Union[dict, list],
362+
default_value: typing.Union[
363+
Sequence[FlagValueType], typing.Mapping[str, FlagValueType]
364+
],
360365
evaluation_context: typing.Optional[EvaluationContext] = None,
361366
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
362-
) -> typing.Union[dict, list]:
367+
) -> typing.Union[Sequence[FlagValueType], typing.Mapping[str, FlagValueType]]:
363368
details = await self.get_object_details_async(
364369
flag_key,
365370
default_value,
@@ -371,10 +376,14 @@ async def get_object_value_async(
371376
def get_object_details(
372377
self,
373378
flag_key: str,
374-
default_value: typing.Union[dict, list],
379+
default_value: typing.Union[
380+
Sequence[FlagValueType], typing.Mapping[str, FlagValueType]
381+
],
375382
evaluation_context: typing.Optional[EvaluationContext] = None,
376383
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
377-
) -> FlagEvaluationDetails[typing.Union[dict, list]]:
384+
) -> FlagEvaluationDetails[
385+
typing.Union[Sequence[FlagValueType], typing.Mapping[str, FlagValueType]]
386+
]:
378387
return self.evaluate_flag_details(
379388
FlagType.OBJECT,
380389
flag_key,
@@ -386,10 +395,14 @@ def get_object_details(
386395
async def get_object_details_async(
387396
self,
388397
flag_key: str,
389-
default_value: typing.Union[dict, list],
398+
default_value: typing.Union[
399+
Sequence[FlagValueType], typing.Mapping[str, FlagValueType]
400+
],
390401
evaluation_context: typing.Optional[EvaluationContext] = None,
391402
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
392-
) -> FlagEvaluationDetails[typing.Union[dict, list]]:
403+
) -> FlagEvaluationDetails[
404+
typing.Union[Sequence[FlagValueType], typing.Mapping[str, FlagValueType]]
405+
]:
393406
return await self.evaluate_flag_details_async(
394407
FlagType.OBJECT,
395408
flag_key,
@@ -402,7 +415,7 @@ def _establish_hooks_and_provider(
402415
self,
403416
flag_type: FlagType,
404417
flag_key: str,
405-
default_value: typing.Any,
418+
default_value: FlagValueType,
406419
evaluation_context: typing.Optional[EvaluationContext],
407420
flag_evaluation_options: typing.Optional[FlagEvaluationOptions],
408421
) -> tuple[
@@ -479,14 +492,74 @@ def _before_hooks_and_merge_context(
479492
)
480493
return merged_context
481494

495+
@typing.overload
496+
async def evaluate_flag_details_async(
497+
self,
498+
flag_type: FlagType,
499+
flag_key: str,
500+
default_value: bool,
501+
evaluation_context: typing.Optional[EvaluationContext] = None,
502+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
503+
) -> FlagEvaluationDetails[bool]: ...
504+
505+
@typing.overload
506+
async def evaluate_flag_details_async(
507+
self,
508+
flag_type: FlagType,
509+
flag_key: str,
510+
default_value: int,
511+
evaluation_context: typing.Optional[EvaluationContext] = None,
512+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
513+
) -> FlagEvaluationDetails[int]: ...
514+
515+
@typing.overload
516+
async def evaluate_flag_details_async(
517+
self,
518+
flag_type: FlagType,
519+
flag_key: str,
520+
default_value: float,
521+
evaluation_context: typing.Optional[EvaluationContext] = None,
522+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
523+
) -> FlagEvaluationDetails[float]: ...
524+
525+
@typing.overload
526+
async def evaluate_flag_details_async(
527+
self,
528+
flag_type: FlagType,
529+
flag_key: str,
530+
default_value: str,
531+
evaluation_context: typing.Optional[EvaluationContext] = None,
532+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
533+
) -> FlagEvaluationDetails[str]: ...
534+
535+
@typing.overload
536+
async def evaluate_flag_details_async(
537+
self,
538+
flag_type: FlagType,
539+
flag_key: str,
540+
default_value: Sequence["FlagValueType"],
541+
evaluation_context: typing.Optional[EvaluationContext] = None,
542+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
543+
) -> FlagEvaluationDetails[Sequence["FlagValueType"]]: ...
544+
545+
@typing.overload
546+
async def evaluate_flag_details_async(
547+
self,
548+
flag_type: FlagType,
549+
flag_key: str,
550+
default_value: typing.Mapping[str, "FlagValueType"],
551+
evaluation_context: typing.Optional[EvaluationContext] = None,
552+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
553+
) -> FlagEvaluationDetails[typing.Mapping[str, "FlagValueType"]]: ...
554+
482555
async def evaluate_flag_details_async(
483556
self,
484557
flag_type: FlagType,
485558
flag_key: str,
486-
default_value: typing.Any,
559+
default_value: FlagValueType,
487560
evaluation_context: typing.Optional[EvaluationContext] = None,
488561
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
489-
) -> FlagEvaluationDetails[typing.Any]:
562+
) -> FlagEvaluationDetails[FlagValueType]:
490563
"""
491564
Evaluate the flag requested by the user from the clients provider.
492565
@@ -595,14 +668,74 @@ async def evaluate_flag_details_async(
595668
hook_hints,
596669
)
597670

671+
@typing.overload
672+
def evaluate_flag_details(
673+
self,
674+
flag_type: FlagType,
675+
flag_key: str,
676+
default_value: bool,
677+
evaluation_context: typing.Optional[EvaluationContext] = None,
678+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
679+
) -> FlagEvaluationDetails[bool]: ...
680+
681+
@typing.overload
682+
def evaluate_flag_details(
683+
self,
684+
flag_type: FlagType,
685+
flag_key: str,
686+
default_value: int,
687+
evaluation_context: typing.Optional[EvaluationContext] = None,
688+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
689+
) -> FlagEvaluationDetails[int]: ...
690+
691+
@typing.overload
692+
def evaluate_flag_details(
693+
self,
694+
flag_type: FlagType,
695+
flag_key: str,
696+
default_value: float,
697+
evaluation_context: typing.Optional[EvaluationContext] = None,
698+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
699+
) -> FlagEvaluationDetails[float]: ...
700+
701+
@typing.overload
702+
def evaluate_flag_details(
703+
self,
704+
flag_type: FlagType,
705+
flag_key: str,
706+
default_value: str,
707+
evaluation_context: typing.Optional[EvaluationContext] = None,
708+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
709+
) -> FlagEvaluationDetails[str]: ...
710+
711+
@typing.overload
712+
def evaluate_flag_details(
713+
self,
714+
flag_type: FlagType,
715+
flag_key: str,
716+
default_value: Sequence["FlagValueType"],
717+
evaluation_context: typing.Optional[EvaluationContext] = None,
718+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
719+
) -> FlagEvaluationDetails[Sequence["FlagValueType"]]: ...
720+
721+
@typing.overload
722+
def evaluate_flag_details(
723+
self,
724+
flag_type: FlagType,
725+
flag_key: str,
726+
default_value: typing.Mapping[str, "FlagValueType"],
727+
evaluation_context: typing.Optional[EvaluationContext] = None,
728+
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
729+
) -> FlagEvaluationDetails[typing.Mapping[str, "FlagValueType"]]: ...
730+
598731
def evaluate_flag_details(
599732
self,
600733
flag_type: FlagType,
601734
flag_key: str,
602-
default_value: typing.Any,
735+
default_value: FlagValueType,
603736
evaluation_context: typing.Optional[EvaluationContext] = None,
604737
flag_evaluation_options: typing.Optional[FlagEvaluationOptions] = None,
605-
) -> FlagEvaluationDetails[typing.Any]:
738+
) -> FlagEvaluationDetails[FlagValueType]:
606739
"""
607740
Evaluate the flag requested by the user from the clients provider.
608741
@@ -718,9 +851,9 @@ async def _create_provider_evaluation_async(
718851
provider: FeatureProvider,
719852
flag_type: FlagType,
720853
flag_key: str,
721-
default_value: typing.Any,
854+
default_value: FlagValueType,
722855
evaluation_context: typing.Optional[EvaluationContext] = None,
723-
) -> FlagEvaluationDetails[typing.Any]:
856+
) -> FlagEvaluationDetails[FlagValueType]:
724857
get_details_callables_async: typing.Mapping[
725858
FlagType, ResolveDetailsCallableAsync
726859
] = {
@@ -765,9 +898,9 @@ def _create_provider_evaluation(
765898
provider: FeatureProvider,
766899
flag_type: FlagType,
767900
flag_key: str,
768-
default_value: typing.Any,
901+
default_value: FlagValueType,
769902
evaluation_context: typing.Optional[EvaluationContext] = None,
770-
) -> FlagEvaluationDetails[typing.Any]:
903+
) -> FlagEvaluationDetails[FlagValueType]:
771904
"""
772905
Encapsulated method to create a FlagEvaluationDetail from a specific provider.
773906

openfeature/evaluation_context/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
from __future__ import annotations
22

33
import typing
4+
from collections.abc import Sequence
45
from dataclasses import dataclass, field
6+
from datetime import datetime
57

68
from openfeature.exception import GeneralError
79

810
__all__ = ["EvaluationContext", "get_evaluation_context", "set_evaluation_context"]
911

12+
# https://openfeature.dev/specification/sections/evaluation-context#requirement-312
13+
EvaluationContextAttributes = typing.Mapping[
14+
str,
15+
typing.Union[
16+
bool,
17+
int,
18+
float,
19+
str,
20+
datetime,
21+
Sequence["EvaluationContextAttributes"],
22+
typing.Mapping[str, "EvaluationContextAttributes"],
23+
],
24+
]
25+
1026

1127
@dataclass
1228
class EvaluationContext:
1329
targeting_key: typing.Optional[str] = None
14-
attributes: dict = field(default_factory=dict)
30+
attributes: EvaluationContextAttributes = field(default_factory=dict)
1531

1632
def merge(self, ctx2: EvaluationContext) -> EvaluationContext:
1733
if not (self and ctx2):

openfeature/flag_evaluation.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import typing
4+
from collections.abc import Sequence
45
from dataclasses import dataclass, field
56

67
from openfeature._backports.strenum import StrEnum
@@ -41,7 +42,15 @@ class Reason(StrEnum):
4142
UNKNOWN = "UNKNOWN"
4243

4344

44-
FlagMetadata = typing.Mapping[str, typing.Any]
45+
FlagMetadata = typing.Mapping[str, typing.Union[bool, int, float, str]]
46+
FlagValueType = typing.Union[
47+
bool,
48+
int,
49+
float,
50+
str,
51+
Sequence["FlagValueType"],
52+
typing.Mapping[str, "FlagValueType"],
53+
]
4554

4655
T_co = typing.TypeVar("T_co", covariant=True)
4756

openfeature/hook/__init__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from __future__ import annotations
22

33
import typing
4+
from collections.abc import Sequence
45
from datetime import datetime
56
from enum import Enum
67
from typing import TYPE_CHECKING
78

89
from openfeature.evaluation_context import EvaluationContext
9-
from openfeature.flag_evaluation import FlagEvaluationDetails, FlagType
10+
from openfeature.flag_evaluation import FlagEvaluationDetails, FlagType, FlagValueType
1011

1112
if TYPE_CHECKING:
1213
from openfeature.client import ClientMetadata
@@ -37,7 +38,7 @@ def __init__(
3738
self,
3839
flag_key: str,
3940
flag_type: FlagType,
40-
default_value: typing.Any,
41+
default_value: FlagValueType,
4142
evaluation_context: EvaluationContext,
4243
client_metadata: typing.Optional[ClientMetadata] = None,
4344
provider_metadata: typing.Optional[Metadata] = None,
@@ -70,8 +71,8 @@ def __setattr__(self, key: str, value: typing.Any) -> None:
7071
float,
7172
str,
7273
datetime,
73-
list[typing.Any],
74-
dict[str, typing.Any],
74+
Sequence["HookHints"],
75+
typing.Mapping[str, "HookHints"],
7576
],
7677
]
7778

@@ -94,7 +95,7 @@ def before(
9495
def after(
9596
self,
9697
hook_context: HookContext,
97-
details: FlagEvaluationDetails[typing.Any],
98+
details: FlagEvaluationDetails[FlagValueType],
9899
hints: HookHints,
99100
) -> None:
100101
"""
@@ -122,7 +123,7 @@ def error(
122123
def finally_after(
123124
self,
124125
hook_context: HookContext,
125-
details: FlagEvaluationDetails[typing.Any],
126+
details: FlagEvaluationDetails[FlagValueType],
126127
hints: HookHints,
127128
) -> None:
128129
"""

0 commit comments

Comments
 (0)