Skip to content

Commit b405925

Browse files
authored
refactor: add mypy and fix typing issues (#72)
* add mypy and fix typing issues Signed-off-by: gruebel <[email protected]> * imrpove callable typing Signed-off-by: gruebel <[email protected]> --------- Signed-off-by: gruebel <[email protected]>
1 parent 9411d0f commit b405925

File tree

5 files changed

+66
-36
lines changed

5 files changed

+66
-36
lines changed

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,13 @@ repos:
1414
- id: check-yaml
1515
- id: trailing-whitespace
1616
- id: check-merge-conflict
17+
18+
- repo: https://github.com/pre-commit/mirrors-mypy
19+
rev: v1.9.0
20+
hooks:
21+
- id: mypy
22+
additional_dependencies:
23+
- openfeature-sdk>=0.4.0
24+
- opentelemetry-api
25+
- types-protobuf
26+
exclude: proto|tests

hooks/openfeature-hooks-opentelemetry/src/openfeature/contrib/hook/opentelemetry/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class EventAttributes:
1616
class TracingHook(Hook):
1717
def after(
1818
self, hook_context: HookContext, details: FlagEvaluationDetails, hints: dict
19-
):
19+
) -> None:
2020
current_span = trace.get_current_span()
2121

2222
variant = details.variant
@@ -38,6 +38,8 @@ def after(
3838

3939
current_span.add_event(OTEL_EVENT_NAME, event_attributes)
4040

41-
def error(self, hook_context: HookContext, exception: Exception, hints: dict):
41+
def error(
42+
self, hook_context: HookContext, exception: Exception, hints: dict
43+
) -> None:
4244
current_span = trace.get_current_span()
4345
current_span.record_exception(exception)

mypy.ini

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[mypy]
2+
files = hooks,providers
3+
exclude = proto|tests
4+
untyped_calls_exclude = flagd.proto
5+
6+
namespace_packages = True
7+
explicit_package_bases = True
8+
local_partial_types = True
9+
pretty = True
10+
strict = True
11+
disallow_any_generics = False
12+
13+
[mypy-flagd.proto.*]
14+
follow_imports = silent
15+
16+
[mypy-grpc]
17+
ignore_missing_imports = True

providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/config.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import os
22
import typing
33

4+
T = typing.TypeVar("T")
5+
46

57
def str_to_bool(val: str) -> bool:
68
return val.lower() == "true"
79

810

9-
def env_or_default(env_var, default, cast=None):
11+
def env_or_default(
12+
env_var: str, default: T, cast: typing.Optional[typing.Callable[[str], T]] = None
13+
) -> typing.Union[str, T]:
1014
val = os.environ.get(env_var)
1115
if val is None:
1216
return default
@@ -17,7 +21,7 @@ class Config:
1721
def __init__(
1822
self,
1923
host: typing.Optional[str] = None,
20-
port: typing.Optional[str] = None,
24+
port: typing.Optional[int] = None,
2125
tls: typing.Optional[bool] = None,
2226
timeout: typing.Optional[int] = None,
2327
):

providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/provider.py

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
"""
2323

2424
import typing
25-
from dataclasses import dataclass
26-
from numbers import Number
2725

2826
import grpc
2927
from google.protobuf.struct_pb2 import Struct
@@ -36,17 +34,15 @@
3634
ParseError,
3735
TypeMismatchError,
3836
)
39-
from openfeature.flag_evaluation import FlagEvaluationDetails
37+
from openfeature.flag_evaluation import FlagResolutionDetails
38+
from openfeature.provider.metadata import Metadata
4039
from openfeature.provider.provider import AbstractProvider
4140

4241
from .config import Config
4342
from .flag_type import FlagType
4443
from .proto.schema.v1 import schema_pb2, schema_pb2_grpc
4544

46-
47-
@dataclass
48-
class Metadata:
49-
name: str
45+
T = typing.TypeVar("T")
5046

5147

5248
class FlagdProvider(AbstractProvider):
@@ -78,85 +74,85 @@ def __init__(
7874
self.channel = channel_factory(f"{self.config.host}:{self.config.port}")
7975
self.stub = schema_pb2_grpc.ServiceStub(self.channel)
8076

81-
def shutdown(self):
77+
def shutdown(self) -> None:
8278
self.channel.close()
8379

84-
def get_metadata(self):
80+
def get_metadata(self) -> Metadata:
8581
"""Returns provider metadata"""
8682
return Metadata(name="FlagdProvider")
8783

8884
def resolve_boolean_details(
8985
self,
9086
key: str,
9187
default_value: bool,
92-
evaluation_context: EvaluationContext = None,
93-
):
88+
evaluation_context: typing.Optional[EvaluationContext] = None,
89+
) -> FlagResolutionDetails[bool]:
9490
return self._resolve(key, FlagType.BOOLEAN, default_value, evaluation_context)
9591

9692
def resolve_string_details(
9793
self,
9894
key: str,
9995
default_value: str,
100-
evaluation_context: EvaluationContext = None,
101-
):
96+
evaluation_context: typing.Optional[EvaluationContext] = None,
97+
) -> FlagResolutionDetails[str]:
10298
return self._resolve(key, FlagType.STRING, default_value, evaluation_context)
10399

104100
def resolve_float_details(
105101
self,
106102
key: str,
107-
default_value: Number,
108-
evaluation_context: EvaluationContext = None,
109-
):
103+
default_value: float,
104+
evaluation_context: typing.Optional[EvaluationContext] = None,
105+
) -> FlagResolutionDetails[float]:
110106
return self._resolve(key, FlagType.FLOAT, default_value, evaluation_context)
111107

112108
def resolve_integer_details(
113109
self,
114110
key: str,
115-
default_value: Number,
116-
evaluation_context: EvaluationContext = None,
117-
):
111+
default_value: int,
112+
evaluation_context: typing.Optional[EvaluationContext] = None,
113+
) -> FlagResolutionDetails[int]:
118114
return self._resolve(key, FlagType.INTEGER, default_value, evaluation_context)
119115

120116
def resolve_object_details(
121117
self,
122118
key: str,
123119
default_value: typing.Union[dict, list],
124-
evaluation_context: EvaluationContext = None,
125-
):
120+
evaluation_context: typing.Optional[EvaluationContext] = None,
121+
) -> FlagResolutionDetails[typing.Union[dict, list]]:
126122
return self._resolve(key, FlagType.OBJECT, default_value, evaluation_context)
127123

128124
def _resolve(
129125
self,
130126
flag_key: str,
131127
flag_type: FlagType,
132-
default_value: typing.Any,
133-
evaluation_context: EvaluationContext,
134-
):
128+
default_value: T,
129+
evaluation_context: typing.Optional[EvaluationContext],
130+
) -> FlagResolutionDetails[T]:
135131
context = self._convert_context(evaluation_context)
136132
call_args = {"timeout": self.config.timeout}
137133
try:
138134
if flag_type == FlagType.BOOLEAN:
139-
request = schema_pb2.ResolveBooleanRequest(
135+
request = schema_pb2.ResolveBooleanRequest( # type:ignore[attr-defined]
140136
flag_key=flag_key, context=context
141137
)
142138
response = self.stub.ResolveBoolean(request, **call_args)
143139
elif flag_type == FlagType.STRING:
144-
request = schema_pb2.ResolveStringRequest(
140+
request = schema_pb2.ResolveStringRequest( # type:ignore[attr-defined]
145141
flag_key=flag_key, context=context
146142
)
147143
response = self.stub.ResolveString(request, **call_args)
148144
elif flag_type == FlagType.OBJECT:
149-
request = schema_pb2.ResolveObjectRequest(
145+
request = schema_pb2.ResolveObjectRequest( # type:ignore[attr-defined]
150146
flag_key=flag_key, context=context
151147
)
152148
response = self.stub.ResolveObject(request, **call_args)
153149
elif flag_type == FlagType.FLOAT:
154-
request = schema_pb2.ResolveFloatRequest(
150+
request = schema_pb2.ResolveFloatRequest( # type:ignore[attr-defined]
155151
flag_key=flag_key, context=context
156152
)
157153
response = self.stub.ResolveFloat(request, **call_args)
158154
elif flag_type == FlagType.INTEGER:
159-
request = schema_pb2.ResolveIntRequest(
155+
request = schema_pb2.ResolveIntRequest( # type:ignore[attr-defined]
160156
flag_key=flag_key, context=context
161157
)
162158
response = self.stub.ResolveInt(request, **call_args)
@@ -176,14 +172,15 @@ def _resolve(
176172
raise GeneralError(message) from e
177173

178174
# Got a valid flag and valid type. Return it.
179-
return FlagEvaluationDetails(
180-
flag_key=flag_key,
175+
return FlagResolutionDetails(
181176
value=response.value,
182177
reason=response.reason,
183178
variant=response.variant,
184179
)
185180

186-
def _convert_context(self, evaluation_context: EvaluationContext):
181+
def _convert_context(
182+
self, evaluation_context: typing.Optional[EvaluationContext]
183+
) -> Struct:
187184
s = Struct()
188185
if evaluation_context:
189186
try:

0 commit comments

Comments
 (0)