devcycle-python-server-sdk 3.11.3__py3-none-any.whl → 3.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devcycle_python_sdk/VERSION.txt +1 -1
- devcycle_python_sdk/api/bucketing_client.py +12 -0
- devcycle_python_sdk/api/local_bucketing.py +0 -8
- devcycle_python_sdk/bucketing-lib.release.wasm +0 -0
- devcycle_python_sdk/cloud_client.py +51 -4
- devcycle_python_sdk/local_client.py +65 -14
- devcycle_python_sdk/managers/eval_hooks_manager.py +73 -0
- devcycle_python_sdk/managers/sse_manager.py +1 -1
- devcycle_python_sdk/models/bucketed_config.py +0 -1
- devcycle_python_sdk/models/eval_hook.py +18 -0
- devcycle_python_sdk/models/eval_hook_context.py +10 -0
- devcycle_python_sdk/models/eval_reason.py +40 -0
- devcycle_python_sdk/models/user.py +16 -4
- devcycle_python_sdk/models/variable.py +44 -6
- devcycle_python_sdk/open_feature_provider/provider.py +10 -5
- devcycle_python_sdk/options.py +8 -1
- devcycle_python_sdk/protobuf/utils.py +18 -0
- devcycle_python_sdk/protobuf/variableForUserParams_pb2.py +43 -30
- devcycle_python_sdk/protobuf/variableForUserParams_pb2.pyi +100 -78
- {devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/METADATA +1 -1
- {devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/RECORD +30 -26
- test/api/test_local_bucketing.py +11 -0
- test/models/test_user.py +90 -0
- test/openfeature_test/test_provider.py +79 -2
- test/openfeature_test/test_provider_local_sdk.py +25 -0
- test/test_cloud_client.py +89 -0
- test/test_local_client.py +97 -1
- {devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/WHEEL +0 -0
- {devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/licenses/LICENSE +0 -0
- {devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/top_level.txt +0 -0
|
@@ -5,6 +5,7 @@ import math
|
|
|
5
5
|
from typing import Any, Optional
|
|
6
6
|
|
|
7
7
|
from devcycle_python_sdk.models.variable import TypeEnum, Variable
|
|
8
|
+
from devcycle_python_sdk.models.eval_reason import EvalReason
|
|
8
9
|
from devcycle_python_sdk.models.user import DevCycleUser
|
|
9
10
|
|
|
10
11
|
import devcycle_python_sdk.protobuf.variableForUserParams_pb2 as pb2
|
|
@@ -82,7 +83,20 @@ def create_dvcuser_pb(user: DevCycleUser) -> pb2.DVCUser_PB: # type: ignore
|
|
|
82
83
|
)
|
|
83
84
|
|
|
84
85
|
|
|
86
|
+
def create_eval_reason_from_pb(eval_reason_pb: pb2.EvalReason_PB) -> EvalReason: # type: ignore
|
|
87
|
+
"""Convert EvalReason_PB protobuf message to EvalReason object"""
|
|
88
|
+
return EvalReason(
|
|
89
|
+
reason=eval_reason_pb.reason,
|
|
90
|
+
details=eval_reason_pb.details if eval_reason_pb.details else None,
|
|
91
|
+
target_id=eval_reason_pb.target_id if eval_reason_pb.target_id else None,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
85
95
|
def create_variable(sdk_variable: pb2.SDKVariable_PB, default_value: Any) -> Variable: # type: ignore
|
|
96
|
+
eval_reason_obj = None
|
|
97
|
+
if sdk_variable.HasField("eval"):
|
|
98
|
+
eval_reason_obj = create_eval_reason_from_pb(sdk_variable.eval)
|
|
99
|
+
|
|
86
100
|
if sdk_variable.type == pb2.VariableType_PB.Boolean: # type: ignore
|
|
87
101
|
return Variable(
|
|
88
102
|
_id=None,
|
|
@@ -91,6 +105,7 @@ def create_variable(sdk_variable: pb2.SDKVariable_PB, default_value: Any) -> Var
|
|
|
91
105
|
type=TypeEnum.BOOLEAN,
|
|
92
106
|
isDefaulted=False,
|
|
93
107
|
defaultValue=default_value,
|
|
108
|
+
eval=eval_reason_obj,
|
|
94
109
|
)
|
|
95
110
|
|
|
96
111
|
elif sdk_variable.type == pb2.VariableType_PB.String: # type: ignore
|
|
@@ -101,6 +116,7 @@ def create_variable(sdk_variable: pb2.SDKVariable_PB, default_value: Any) -> Var
|
|
|
101
116
|
type=TypeEnum.STRING,
|
|
102
117
|
isDefaulted=False,
|
|
103
118
|
defaultValue=default_value,
|
|
119
|
+
eval=eval_reason_obj,
|
|
104
120
|
)
|
|
105
121
|
|
|
106
122
|
elif sdk_variable.type == pb2.VariableType_PB.Number: # type: ignore
|
|
@@ -111,6 +127,7 @@ def create_variable(sdk_variable: pb2.SDKVariable_PB, default_value: Any) -> Var
|
|
|
111
127
|
type=TypeEnum.NUMBER,
|
|
112
128
|
isDefaulted=False,
|
|
113
129
|
defaultValue=default_value,
|
|
130
|
+
eval=eval_reason_obj,
|
|
114
131
|
)
|
|
115
132
|
|
|
116
133
|
elif sdk_variable.type == pb2.VariableType_PB.JSON: # type: ignore
|
|
@@ -123,6 +140,7 @@ def create_variable(sdk_variable: pb2.SDKVariable_PB, default_value: Any) -> Var
|
|
|
123
140
|
type=TypeEnum.JSON,
|
|
124
141
|
isDefaulted=False,
|
|
125
142
|
defaultValue=default_value,
|
|
143
|
+
eval=eval_reason_obj,
|
|
126
144
|
)
|
|
127
145
|
|
|
128
146
|
else:
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
3
4
|
# source: variableForUserParams.proto
|
|
5
|
+
# Protobuf Python Version: 5.29.3
|
|
4
6
|
"""Generated protocol buffer code."""
|
|
5
|
-
from google.protobuf.internal import builder as _builder
|
|
6
7
|
from google.protobuf import descriptor as _descriptor
|
|
7
8
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
8
10
|
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
5,
|
|
15
|
+
29,
|
|
16
|
+
3,
|
|
17
|
+
'',
|
|
18
|
+
'variableForUserParams.proto'
|
|
19
|
+
)
|
|
9
20
|
# @@protoc_insertion_point(imports)
|
|
10
21
|
|
|
11
22
|
_sym_db = _symbol_database.Default()
|
|
@@ -13,34 +24,36 @@ _sym_db = _symbol_database.Default()
|
|
|
13
24
|
|
|
14
25
|
|
|
15
26
|
|
|
16
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bvariableForUserParams.proto\"/\n\x0eNullableString\x12\r\n\x05value\x18\x01 \x01(\t\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\"/\n\x0eNullableDouble\x12\r\n\x05value\x18\x01 \x01(\x01\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\"m\n\x0f\x43ustomDataValue\x12\x1d\n\x04type\x18\x01 \x01(\x0e\x32\x0f.CustomDataType\x12\x11\n\tboolValue\x18\x02 \x01(\x08\x12\x13\n\x0b\x64oubleValue\x18\x03 \x01(\x01\x12\x13\n\x0bstringValue\x18\x04 \x01(\t\"\x93\x01\n\x12NullableCustomData\x12-\n\x05value\x18\x01 \x03(\x0b\x32\x1e.NullableCustomData.ValueEntry\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\x1a>\n\nValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1f\n\x05value\x18\x02 \x01(\x0b\x32\x10.CustomDataValue:\x02\x38\x01\"\x9c\x01\n\x18VariableForUserParams_PB\x12\x0e\n\x06sdkKey\x18\x01 \x01(\t\x12\x13\n\x0bvariableKey\x18\x02 \x01(\t\x12&\n\x0cvariableType\x18\x03 \x01(\x0e\x32\x10.VariableType_PB\x12\x19\n\x04user\x18\x04 \x01(\x0b\x32\x0b.DVCUser_PB\x12\x18\n\x10shouldTrackEvent\x18\x05 \x01(\x08\"\xe8\x02\n\nDVCUser_PB\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x1e\n\x05\x65mail\x18\x02 \x01(\x0b\x32\x0f.NullableString\x12\x1d\n\x04name\x18\x03 \x01(\x0b\x32\x0f.NullableString\x12!\n\x08language\x18\x04 \x01(\x0b\x32\x0f.NullableString\x12 \n\x07\x63ountry\x18\x05 \x01(\x0b\x32\x0f.NullableString\x12!\n\x08\x61ppBuild\x18\x06 \x01(\x0b\x32\x0f.NullableDouble\x12#\n\nappVersion\x18\x07 \x01(\x0b\x32\x0f.NullableString\x12$\n\x0b\x64\x65viceModel\x18\x08 \x01(\x0b\x32\x0f.NullableString\x12\'\n\ncustomData\x18\t \x01(\x0b\x32\x13.NullableCustomData\x12.\n\x11privateCustomData\x18\n \x01(\x0b\x32\x13.NullableCustomData\"\
|
|
17
|
-
|
|
18
|
-
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
|
19
|
-
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'variableForUserParams_pb2', globals())
|
|
20
|
-
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bvariableForUserParams.proto\"/\n\x0eNullableString\x12\r\n\x05value\x18\x01 \x01(\t\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\"/\n\x0eNullableDouble\x12\r\n\x05value\x18\x01 \x01(\x01\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\"m\n\x0f\x43ustomDataValue\x12\x1d\n\x04type\x18\x01 \x01(\x0e\x32\x0f.CustomDataType\x12\x11\n\tboolValue\x18\x02 \x01(\x08\x12\x13\n\x0b\x64oubleValue\x18\x03 \x01(\x01\x12\x13\n\x0bstringValue\x18\x04 \x01(\t\"\x93\x01\n\x12NullableCustomData\x12-\n\x05value\x18\x01 \x03(\x0b\x32\x1e.NullableCustomData.ValueEntry\x12\x0e\n\x06isNull\x18\x02 \x01(\x08\x1a>\n\nValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1f\n\x05value\x18\x02 \x01(\x0b\x32\x10.CustomDataValue:\x02\x38\x01\"\x9c\x01\n\x18VariableForUserParams_PB\x12\x0e\n\x06sdkKey\x18\x01 \x01(\t\x12\x13\n\x0bvariableKey\x18\x02 \x01(\t\x12&\n\x0cvariableType\x18\x03 \x01(\x0e\x32\x10.VariableType_PB\x12\x19\n\x04user\x18\x04 \x01(\x0b\x32\x0b.DVCUser_PB\x12\x18\n\x10shouldTrackEvent\x18\x05 \x01(\x08\"\xe8\x02\n\nDVCUser_PB\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x1e\n\x05\x65mail\x18\x02 \x01(\x0b\x32\x0f.NullableString\x12\x1d\n\x04name\x18\x03 \x01(\x0b\x32\x0f.NullableString\x12!\n\x08language\x18\x04 \x01(\x0b\x32\x0f.NullableString\x12 \n\x07\x63ountry\x18\x05 \x01(\x0b\x32\x0f.NullableString\x12!\n\x08\x61ppBuild\x18\x06 \x01(\x0b\x32\x0f.NullableDouble\x12#\n\nappVersion\x18\x07 \x01(\x0b\x32\x0f.NullableString\x12$\n\x0b\x64\x65viceModel\x18\x08 \x01(\x0b\x32\x0f.NullableString\x12\'\n\ncustomData\x18\t \x01(\x0b\x32\x13.NullableCustomData\x12.\n\x11privateCustomData\x18\n \x01(\x0b\x32\x13.NullableCustomData\"\xed\x01\n\x0eSDKVariable_PB\x12\x0b\n\x03_id\x18\x01 \x01(\t\x12\x1e\n\x04type\x18\x02 \x01(\x0e\x32\x10.VariableType_PB\x12\x0b\n\x03key\x18\x03 \x01(\t\x12\x11\n\tboolValue\x18\x04 \x01(\x08\x12\x13\n\x0b\x64oubleValue\x18\x05 \x01(\x01\x12\x13\n\x0bstringValue\x18\x06 \x01(\t\x12#\n\nevalReason\x18\x07 \x01(\x0b\x32\x0f.NullableString\x12!\n\x08_feature\x18\x08 \x01(\x0b\x32\x0f.NullableString\x12\x1c\n\x04\x65val\x18\t \x01(\x0b\x32\x0e.EvalReason_PB\"C\n\rEvalReason_PB\x12\x0e\n\x06reason\x18\x01 \x01(\t\x12\x0f\n\x07\x64\x65tails\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t*@\n\x0fVariableType_PB\x12\x0b\n\x07\x42oolean\x10\x00\x12\n\n\x06Number\x10\x01\x12\n\n\x06String\x10\x02\x12\x08\n\x04JSON\x10\x03*6\n\x0e\x43ustomDataType\x12\x08\n\x04\x42ool\x10\x00\x12\x07\n\x03Num\x10\x01\x12\x07\n\x03Str\x10\x02\x12\x08\n\x04Null\x10\x03\x42X\n&com.devcycle.sdk.server.local.protobufP\x01Z\x07./proto\xaa\x02\"DevCycle.SDK.Server.Local.Protobufb\x06proto3')
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'variableForUserParams_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n&com.devcycle.sdk.server.local.protobufP\001Z\007./proto\252\002\"DevCycle.SDK.Server.Local.Protobuf'
|
|
35
|
+
_globals['_NULLABLECUSTOMDATA_VALUEENTRY']._loaded_options = None
|
|
36
|
+
_globals['_NULLABLECUSTOMDATA_VALUEENTRY']._serialized_options = b'8\001'
|
|
37
|
+
_globals['_VARIABLETYPE_PB']._serialized_start=1221
|
|
38
|
+
_globals['_VARIABLETYPE_PB']._serialized_end=1285
|
|
39
|
+
_globals['_CUSTOMDATATYPE']._serialized_start=1287
|
|
40
|
+
_globals['_CUSTOMDATATYPE']._serialized_end=1341
|
|
41
|
+
_globals['_NULLABLESTRING']._serialized_start=31
|
|
42
|
+
_globals['_NULLABLESTRING']._serialized_end=78
|
|
43
|
+
_globals['_NULLABLEDOUBLE']._serialized_start=80
|
|
44
|
+
_globals['_NULLABLEDOUBLE']._serialized_end=127
|
|
45
|
+
_globals['_CUSTOMDATAVALUE']._serialized_start=129
|
|
46
|
+
_globals['_CUSTOMDATAVALUE']._serialized_end=238
|
|
47
|
+
_globals['_NULLABLECUSTOMDATA']._serialized_start=241
|
|
48
|
+
_globals['_NULLABLECUSTOMDATA']._serialized_end=388
|
|
49
|
+
_globals['_NULLABLECUSTOMDATA_VALUEENTRY']._serialized_start=326
|
|
50
|
+
_globals['_NULLABLECUSTOMDATA_VALUEENTRY']._serialized_end=388
|
|
51
|
+
_globals['_VARIABLEFORUSERPARAMS_PB']._serialized_start=391
|
|
52
|
+
_globals['_VARIABLEFORUSERPARAMS_PB']._serialized_end=547
|
|
53
|
+
_globals['_DVCUSER_PB']._serialized_start=550
|
|
54
|
+
_globals['_DVCUSER_PB']._serialized_end=910
|
|
55
|
+
_globals['_SDKVARIABLE_PB']._serialized_start=913
|
|
56
|
+
_globals['_SDKVARIABLE_PB']._serialized_end=1150
|
|
57
|
+
_globals['_EVALREASON_PB']._serialized_start=1152
|
|
58
|
+
_globals['_EVALREASON_PB']._serialized_end=1219
|
|
46
59
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -4,117 +4,139 @@ from google.protobuf import descriptor as _descriptor
|
|
|
4
4
|
from google.protobuf import message as _message
|
|
5
5
|
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
|
|
6
6
|
|
|
7
|
-
Bool: CustomDataType
|
|
8
|
-
Boolean: VariableType_PB
|
|
9
7
|
DESCRIPTOR: _descriptor.FileDescriptor
|
|
8
|
+
|
|
9
|
+
class VariableType_PB(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
|
10
|
+
__slots__ = ()
|
|
11
|
+
Boolean: _ClassVar[VariableType_PB]
|
|
12
|
+
Number: _ClassVar[VariableType_PB]
|
|
13
|
+
String: _ClassVar[VariableType_PB]
|
|
14
|
+
JSON: _ClassVar[VariableType_PB]
|
|
15
|
+
|
|
16
|
+
class CustomDataType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
|
17
|
+
__slots__ = ()
|
|
18
|
+
Bool: _ClassVar[CustomDataType]
|
|
19
|
+
Num: _ClassVar[CustomDataType]
|
|
20
|
+
Str: _ClassVar[CustomDataType]
|
|
21
|
+
Null: _ClassVar[CustomDataType]
|
|
22
|
+
Boolean: VariableType_PB
|
|
23
|
+
Number: VariableType_PB
|
|
24
|
+
String: VariableType_PB
|
|
10
25
|
JSON: VariableType_PB
|
|
11
|
-
|
|
26
|
+
Bool: CustomDataType
|
|
12
27
|
Num: CustomDataType
|
|
13
|
-
Number: VariableType_PB
|
|
14
28
|
Str: CustomDataType
|
|
15
|
-
|
|
29
|
+
Null: CustomDataType
|
|
30
|
+
|
|
31
|
+
class NullableString(_message.Message):
|
|
32
|
+
__slots__ = ("value", "isNull")
|
|
33
|
+
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
34
|
+
ISNULL_FIELD_NUMBER: _ClassVar[int]
|
|
35
|
+
value: str
|
|
36
|
+
isNull: bool
|
|
37
|
+
def __init__(self, value: _Optional[str] = ..., isNull: bool = ...) -> None: ...
|
|
38
|
+
|
|
39
|
+
class NullableDouble(_message.Message):
|
|
40
|
+
__slots__ = ("value", "isNull")
|
|
41
|
+
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
42
|
+
ISNULL_FIELD_NUMBER: _ClassVar[int]
|
|
43
|
+
value: float
|
|
44
|
+
isNull: bool
|
|
45
|
+
def __init__(self, value: _Optional[float] = ..., isNull: bool = ...) -> None: ...
|
|
16
46
|
|
|
17
47
|
class CustomDataValue(_message.Message):
|
|
18
|
-
__slots__ =
|
|
48
|
+
__slots__ = ("type", "boolValue", "doubleValue", "stringValue")
|
|
49
|
+
TYPE_FIELD_NUMBER: _ClassVar[int]
|
|
19
50
|
BOOLVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
20
51
|
DOUBLEVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
21
52
|
STRINGVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
22
|
-
|
|
53
|
+
type: CustomDataType
|
|
23
54
|
boolValue: bool
|
|
24
55
|
doubleValue: float
|
|
25
56
|
stringValue: str
|
|
26
|
-
type: CustomDataType
|
|
27
57
|
def __init__(self, type: _Optional[_Union[CustomDataType, str]] = ..., boolValue: bool = ..., doubleValue: _Optional[float] = ..., stringValue: _Optional[str] = ...) -> None: ...
|
|
28
58
|
|
|
29
|
-
class DVCUser_PB(_message.Message):
|
|
30
|
-
__slots__ = ["appBuild", "appVersion", "country", "customData", "deviceModel", "email", "language", "name", "privateCustomData", "user_id"]
|
|
31
|
-
APPBUILD_FIELD_NUMBER: _ClassVar[int]
|
|
32
|
-
APPVERSION_FIELD_NUMBER: _ClassVar[int]
|
|
33
|
-
COUNTRY_FIELD_NUMBER: _ClassVar[int]
|
|
34
|
-
CUSTOMDATA_FIELD_NUMBER: _ClassVar[int]
|
|
35
|
-
DEVICEMODEL_FIELD_NUMBER: _ClassVar[int]
|
|
36
|
-
EMAIL_FIELD_NUMBER: _ClassVar[int]
|
|
37
|
-
LANGUAGE_FIELD_NUMBER: _ClassVar[int]
|
|
38
|
-
NAME_FIELD_NUMBER: _ClassVar[int]
|
|
39
|
-
PRIVATECUSTOMDATA_FIELD_NUMBER: _ClassVar[int]
|
|
40
|
-
USER_ID_FIELD_NUMBER: _ClassVar[int]
|
|
41
|
-
appBuild: NullableDouble
|
|
42
|
-
appVersion: NullableString
|
|
43
|
-
country: NullableString
|
|
44
|
-
customData: NullableCustomData
|
|
45
|
-
deviceModel: NullableString
|
|
46
|
-
email: NullableString
|
|
47
|
-
language: NullableString
|
|
48
|
-
name: NullableString
|
|
49
|
-
privateCustomData: NullableCustomData
|
|
50
|
-
user_id: str
|
|
51
|
-
def __init__(self, user_id: _Optional[str] = ..., email: _Optional[_Union[NullableString, _Mapping]] = ..., name: _Optional[_Union[NullableString, _Mapping]] = ..., language: _Optional[_Union[NullableString, _Mapping]] = ..., country: _Optional[_Union[NullableString, _Mapping]] = ..., appBuild: _Optional[_Union[NullableDouble, _Mapping]] = ..., appVersion: _Optional[_Union[NullableString, _Mapping]] = ..., deviceModel: _Optional[_Union[NullableString, _Mapping]] = ..., customData: _Optional[_Union[NullableCustomData, _Mapping]] = ..., privateCustomData: _Optional[_Union[NullableCustomData, _Mapping]] = ...) -> None: ...
|
|
52
|
-
|
|
53
59
|
class NullableCustomData(_message.Message):
|
|
54
|
-
__slots__ =
|
|
60
|
+
__slots__ = ("value", "isNull")
|
|
55
61
|
class ValueEntry(_message.Message):
|
|
56
|
-
__slots__ =
|
|
62
|
+
__slots__ = ("key", "value")
|
|
57
63
|
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
58
64
|
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
59
65
|
key: str
|
|
60
66
|
value: CustomDataValue
|
|
61
67
|
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[CustomDataValue, _Mapping]] = ...) -> None: ...
|
|
62
|
-
ISNULL_FIELD_NUMBER: _ClassVar[int]
|
|
63
68
|
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
64
|
-
|
|
69
|
+
ISNULL_FIELD_NUMBER: _ClassVar[int]
|
|
65
70
|
value: _containers.MessageMap[str, CustomDataValue]
|
|
71
|
+
isNull: bool
|
|
66
72
|
def __init__(self, value: _Optional[_Mapping[str, CustomDataValue]] = ..., isNull: bool = ...) -> None: ...
|
|
67
73
|
|
|
68
|
-
class
|
|
69
|
-
__slots__ =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
class VariableForUserParams_PB(_message.Message):
|
|
75
|
+
__slots__ = ("sdkKey", "variableKey", "variableType", "user", "shouldTrackEvent")
|
|
76
|
+
SDKKEY_FIELD_NUMBER: _ClassVar[int]
|
|
77
|
+
VARIABLEKEY_FIELD_NUMBER: _ClassVar[int]
|
|
78
|
+
VARIABLETYPE_FIELD_NUMBER: _ClassVar[int]
|
|
79
|
+
USER_FIELD_NUMBER: _ClassVar[int]
|
|
80
|
+
SHOULDTRACKEVENT_FIELD_NUMBER: _ClassVar[int]
|
|
81
|
+
sdkKey: str
|
|
82
|
+
variableKey: str
|
|
83
|
+
variableType: VariableType_PB
|
|
84
|
+
user: DVCUser_PB
|
|
85
|
+
shouldTrackEvent: bool
|
|
86
|
+
def __init__(self, sdkKey: _Optional[str] = ..., variableKey: _Optional[str] = ..., variableType: _Optional[_Union[VariableType_PB, str]] = ..., user: _Optional[_Union[DVCUser_PB, _Mapping]] = ..., shouldTrackEvent: bool = ...) -> None: ...
|
|
75
87
|
|
|
76
|
-
class
|
|
77
|
-
__slots__ =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
class DVCUser_PB(_message.Message):
|
|
89
|
+
__slots__ = ("user_id", "email", "name", "language", "country", "appBuild", "appVersion", "deviceModel", "customData", "privateCustomData")
|
|
90
|
+
USER_ID_FIELD_NUMBER: _ClassVar[int]
|
|
91
|
+
EMAIL_FIELD_NUMBER: _ClassVar[int]
|
|
92
|
+
NAME_FIELD_NUMBER: _ClassVar[int]
|
|
93
|
+
LANGUAGE_FIELD_NUMBER: _ClassVar[int]
|
|
94
|
+
COUNTRY_FIELD_NUMBER: _ClassVar[int]
|
|
95
|
+
APPBUILD_FIELD_NUMBER: _ClassVar[int]
|
|
96
|
+
APPVERSION_FIELD_NUMBER: _ClassVar[int]
|
|
97
|
+
DEVICEMODEL_FIELD_NUMBER: _ClassVar[int]
|
|
98
|
+
CUSTOMDATA_FIELD_NUMBER: _ClassVar[int]
|
|
99
|
+
PRIVATECUSTOMDATA_FIELD_NUMBER: _ClassVar[int]
|
|
100
|
+
user_id: str
|
|
101
|
+
email: NullableString
|
|
102
|
+
name: NullableString
|
|
103
|
+
language: NullableString
|
|
104
|
+
country: NullableString
|
|
105
|
+
appBuild: NullableDouble
|
|
106
|
+
appVersion: NullableString
|
|
107
|
+
deviceModel: NullableString
|
|
108
|
+
customData: NullableCustomData
|
|
109
|
+
privateCustomData: NullableCustomData
|
|
110
|
+
def __init__(self, user_id: _Optional[str] = ..., email: _Optional[_Union[NullableString, _Mapping]] = ..., name: _Optional[_Union[NullableString, _Mapping]] = ..., language: _Optional[_Union[NullableString, _Mapping]] = ..., country: _Optional[_Union[NullableString, _Mapping]] = ..., appBuild: _Optional[_Union[NullableDouble, _Mapping]] = ..., appVersion: _Optional[_Union[NullableString, _Mapping]] = ..., deviceModel: _Optional[_Union[NullableString, _Mapping]] = ..., customData: _Optional[_Union[NullableCustomData, _Mapping]] = ..., privateCustomData: _Optional[_Union[NullableCustomData, _Mapping]] = ...) -> None: ...
|
|
83
111
|
|
|
84
112
|
class SDKVariable_PB(_message.Message):
|
|
85
|
-
__slots__ =
|
|
113
|
+
__slots__ = ("_id", "type", "key", "boolValue", "doubleValue", "stringValue", "evalReason", "_feature", "eval")
|
|
114
|
+
_ID_FIELD_NUMBER: _ClassVar[int]
|
|
115
|
+
TYPE_FIELD_NUMBER: _ClassVar[int]
|
|
116
|
+
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
86
117
|
BOOLVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
87
118
|
DOUBLEVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
88
|
-
EVALREASON_FIELD_NUMBER: _ClassVar[int]
|
|
89
|
-
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
90
119
|
STRINGVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
91
|
-
|
|
92
|
-
|
|
120
|
+
EVALREASON_FIELD_NUMBER: _ClassVar[int]
|
|
121
|
+
_FEATURE_FIELD_NUMBER: _ClassVar[int]
|
|
122
|
+
EVAL_FIELD_NUMBER: _ClassVar[int]
|
|
93
123
|
_id: str
|
|
124
|
+
type: VariableType_PB
|
|
125
|
+
key: str
|
|
94
126
|
boolValue: bool
|
|
95
127
|
doubleValue: float
|
|
96
|
-
evalReason: NullableString
|
|
97
|
-
key: str
|
|
98
128
|
stringValue: str
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
__slots__ = ["sdkKey", "shouldTrackEvent", "user", "variableKey", "variableType"]
|
|
104
|
-
SDKKEY_FIELD_NUMBER: _ClassVar[int]
|
|
105
|
-
SHOULDTRACKEVENT_FIELD_NUMBER: _ClassVar[int]
|
|
106
|
-
USER_FIELD_NUMBER: _ClassVar[int]
|
|
107
|
-
VARIABLEKEY_FIELD_NUMBER: _ClassVar[int]
|
|
108
|
-
VARIABLETYPE_FIELD_NUMBER: _ClassVar[int]
|
|
109
|
-
sdkKey: str
|
|
110
|
-
shouldTrackEvent: bool
|
|
111
|
-
user: DVCUser_PB
|
|
112
|
-
variableKey: str
|
|
113
|
-
variableType: VariableType_PB
|
|
114
|
-
def __init__(self, sdkKey: _Optional[str] = ..., variableKey: _Optional[str] = ..., variableType: _Optional[_Union[VariableType_PB, str]] = ..., user: _Optional[_Union[DVCUser_PB, _Mapping]] = ..., shouldTrackEvent: bool = ...) -> None: ...
|
|
115
|
-
|
|
116
|
-
class VariableType_PB(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
|
117
|
-
__slots__ = []
|
|
129
|
+
evalReason: NullableString
|
|
130
|
+
_feature: NullableString
|
|
131
|
+
eval: EvalReason_PB
|
|
132
|
+
def __init__(self, _id: _Optional[str] = ..., type: _Optional[_Union[VariableType_PB, str]] = ..., key: _Optional[str] = ..., boolValue: bool = ..., doubleValue: _Optional[float] = ..., stringValue: _Optional[str] = ..., evalReason: _Optional[_Union[NullableString, _Mapping]] = ..., _feature: _Optional[_Union[NullableString, _Mapping]] = ..., eval: _Optional[_Union[EvalReason_PB, _Mapping]] = ...) -> None: ...
|
|
118
133
|
|
|
119
|
-
class
|
|
120
|
-
__slots__ =
|
|
134
|
+
class EvalReason_PB(_message.Message):
|
|
135
|
+
__slots__ = ("reason", "details", "target_id")
|
|
136
|
+
REASON_FIELD_NUMBER: _ClassVar[int]
|
|
137
|
+
DETAILS_FIELD_NUMBER: _ClassVar[int]
|
|
138
|
+
TARGET_ID_FIELD_NUMBER: _ClassVar[int]
|
|
139
|
+
reason: str
|
|
140
|
+
details: str
|
|
141
|
+
target_id: str
|
|
142
|
+
def __init__(self, reason: _Optional[str] = ..., details: _Optional[str] = ..., target_id: _Optional[str] = ...) -> None: ...
|
{devcycle_python_server_sdk-3.11.3.dist-info → devcycle_python_server_sdk-3.12.0.dist-info}/RECORD
RENAMED
|
@@ -1,52 +1,56 @@
|
|
|
1
|
-
devcycle_python_sdk/VERSION.txt,sha256=
|
|
1
|
+
devcycle_python_sdk/VERSION.txt,sha256=TuPL9BzJKZqNU-jwsDtquUrxVYO4LjhqEL1HqlHKDZU,7
|
|
2
2
|
devcycle_python_sdk/__init__.py,sha256=30TcYb9PbvVi97gwk16omCGG1UoUI9lmmU7xpvxNMvc,336
|
|
3
|
-
devcycle_python_sdk/bucketing-lib.release.wasm,sha256=
|
|
4
|
-
devcycle_python_sdk/cloud_client.py,sha256=
|
|
3
|
+
devcycle_python_sdk/bucketing-lib.release.wasm,sha256=wpbXlOj_TVIO2OcOD781sW5ICmGsYe9pvxG6DwYw6FY,223167
|
|
4
|
+
devcycle_python_sdk/cloud_client.py,sha256=LMKB6gEuQNn5YePUPO0t1QIAUXot4OyshSUlUbuu07U,9413
|
|
5
5
|
devcycle_python_sdk/devcycle_client.py,sha256=OqNza7OXOSRmMQq2kmyivljmH1GyN4dTiz0EhvDvt8w,1069
|
|
6
6
|
devcycle_python_sdk/exceptions.py,sha256=Et7fS8pEFbHkFY86T2pJoEUstwjh4_rzhJxVH8fzAns,1053
|
|
7
|
-
devcycle_python_sdk/local_client.py,sha256=
|
|
8
|
-
devcycle_python_sdk/options.py,sha256=
|
|
7
|
+
devcycle_python_sdk/local_client.py,sha256=obZlHBJ9MS79sntdpPb4JTwC29e58Q5PzzEtei3m9F0,11684
|
|
8
|
+
devcycle_python_sdk/options.py,sha256=W3vNZfV6QNnQyaOuRf6Z5cK6ut6fWtlGqlUfhzWX0_c,5253
|
|
9
9
|
devcycle_python_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
devcycle_python_sdk/api/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
11
11
|
devcycle_python_sdk/api/backoff.py,sha256=F6WYCloaZD9CjNu6mKBMq7K20S8-i2WVU6X05ZRoawE,303
|
|
12
|
-
devcycle_python_sdk/api/bucketing_client.py,sha256
|
|
12
|
+
devcycle_python_sdk/api/bucketing_client.py,sha256=BRQWtTnIyLdWoFT7sPHPGg8kstDtW-jx1N4og3_SEgI,5565
|
|
13
13
|
devcycle_python_sdk/api/config_client.py,sha256=73aQAq130rTHpQrVDX6n_DwFKz0WuKxRoLDiE3vSoAM,5077
|
|
14
14
|
devcycle_python_sdk/api/event_client.py,sha256=WxkuV6geEC9MgG4FN36HeEQQa22ilq2mkOVMZkpiEk4,3356
|
|
15
|
-
devcycle_python_sdk/api/local_bucketing.py,sha256=
|
|
15
|
+
devcycle_python_sdk/api/local_bucketing.py,sha256=IXOP-680OmaO1XoX31YwY8FychAD5aqeyFFGe9SE_u4,15949
|
|
16
16
|
devcycle_python_sdk/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
devcycle_python_sdk/managers/config_manager.py,sha256=AIGY9jXEhUzhEeaKIA1P5F2q6GaclrezAoGHgYU4dLQ,5634
|
|
18
|
+
devcycle_python_sdk/managers/eval_hooks_manager.py,sha256=skOGK_hyZNpgkdeNXTTa-d1GVRITjoi8T6dO5I_Cqfk,2679
|
|
18
19
|
devcycle_python_sdk/managers/event_queue_manager.py,sha256=uPy1vO6OAisZjUNAhWELE_g17alTiOcPv42z-WwkGck,8110
|
|
19
|
-
devcycle_python_sdk/managers/sse_manager.py,sha256=
|
|
20
|
+
devcycle_python_sdk/managers/sse_manager.py,sha256=hSGpnZ6gNbQXGotqNxjogoB82znAyMMFhqdlqeCc5bI,2586
|
|
20
21
|
devcycle_python_sdk/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
devcycle_python_sdk/models/bucketed_config.py,sha256=
|
|
22
|
+
devcycle_python_sdk/models/bucketed_config.py,sha256=qTfhIViX7m2WS2oDBBCmKKzPsJG6DEav3zCEXwP27nA,3980
|
|
22
23
|
devcycle_python_sdk/models/error_response.py,sha256=r_dRUDAbral9UGaMYcnBsZOr9Hmkyi1SQbhGmZilgpA,442
|
|
24
|
+
devcycle_python_sdk/models/eval_hook.py,sha256=_mDoEa8gkzMq-XpFRZrcXu_ldtpUzv5tlh-PghLpMMI,590
|
|
25
|
+
devcycle_python_sdk/models/eval_hook_context.py,sha256=uBa8t0XxbcPBYAewNPFC2902qCjGhVoqUzZOZbGZ3n0,267
|
|
26
|
+
devcycle_python_sdk/models/eval_reason.py,sha256=nMXcbR1DM8eriCQ1NNnIRQKkhJSYAbY8_9GgBfj7P8k,943
|
|
23
27
|
devcycle_python_sdk/models/event.py,sha256=Sj3eEopuPp8QwQl_Oz8E6Y9Ph6nLG0HxU7eR7xSbA7g,3722
|
|
24
28
|
devcycle_python_sdk/models/feature.py,sha256=m3wxxIjC5jxhKpPLI4RcsBaNLuy-zsMqoAgc8ySPe0I,852
|
|
25
29
|
devcycle_python_sdk/models/platform_data.py,sha256=nyQsgI6pcTd1FL3Y2ACmpvTYb08R_UtWul25OWZstps,849
|
|
26
|
-
devcycle_python_sdk/models/user.py,sha256
|
|
27
|
-
devcycle_python_sdk/models/variable.py,sha256=
|
|
30
|
+
devcycle_python_sdk/models/user.py,sha256=mhEk-mnKJRg_tydpBlAVhGDj9rDCacJ-jNwiGeSpZiE,7027
|
|
31
|
+
devcycle_python_sdk/models/variable.py,sha256=NXubhYWXYRAUEh4kDe2Tu9T5QnZmQ3roYVPbP-u2H3s,3030
|
|
28
32
|
devcycle_python_sdk/open_feature_provider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
devcycle_python_sdk/open_feature_provider/provider.py,sha256=
|
|
33
|
+
devcycle_python_sdk/open_feature_provider/provider.py,sha256=l-psKU5m6jSBE53VwX3fBBas-TztekFDlfYTyTJQm6c,5558
|
|
30
34
|
devcycle_python_sdk/protobuf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
devcycle_python_sdk/protobuf/utils.py,sha256=
|
|
32
|
-
devcycle_python_sdk/protobuf/variableForUserParams_pb2.py,sha256=
|
|
33
|
-
devcycle_python_sdk/protobuf/variableForUserParams_pb2.pyi,sha256=
|
|
35
|
+
devcycle_python_sdk/protobuf/utils.py,sha256=6cBL8GZ5nCZw6JoO7lAdgCj9wM1u0lp6QFQMnGE1fiM,5414
|
|
36
|
+
devcycle_python_sdk/protobuf/variableForUserParams_pb2.py,sha256=yawFsQ7m-6OB7DxrjXo2FLLkHhiTv6lDnjubhjAgw_8,5198
|
|
37
|
+
devcycle_python_sdk/protobuf/variableForUserParams_pb2.pyi,sha256=tfN0zBapUPA9WGqUG5lU5XXgH_BsHTt5mgXKGsyS4-I,6623
|
|
34
38
|
devcycle_python_sdk/util/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
35
39
|
devcycle_python_sdk/util/strings.py,sha256=gH0Xm3gIXNqn6hczKPk10Jn5_9knuD7OB5MrB7bqztw,252
|
|
36
40
|
devcycle_python_sdk/util/version.py,sha256=Cz7Us_EuXP-T8GI47g2WHYdBJj_zKo-5y545IDHJAjI,253
|
|
37
|
-
devcycle_python_server_sdk-3.
|
|
41
|
+
devcycle_python_server_sdk-3.12.0.dist-info/licenses/LICENSE,sha256=tHQMqu-Jic2UpMGqb-vNFbGygysl8IG4l1clnnh0OFo,1071
|
|
38
42
|
example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
43
|
example/cloud_client_example.py,sha256=YD8ZsTv3dPYfbFUKraRpRT0VsJGrPwjm8ZCuA5H54yI,2463
|
|
40
44
|
example/local_bucketing_client_example.py,sha256=TaIfy3VnW9fXii9NPYs5UOuP4fLKruXMjnZApveqzl4,2796
|
|
41
45
|
example/openfeature_example.py,sha256=kO6F-Xk20l6CPiMfIxSRreshEGmHMFHRg3zbeLXa3AI,2410
|
|
42
46
|
test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
-
test/test_cloud_client.py,sha256=
|
|
44
|
-
test/test_local_client.py,sha256=
|
|
47
|
+
test/test_cloud_client.py,sha256=oqOWh4aa07ObJOJeEjXMon0O2jPW_lYZMVInbFR-uzI,14586
|
|
48
|
+
test/test_local_client.py,sha256=d0D0h2vqSiZItiqGXrlFXRRmuZG-TNg8MT84dY6w0Ks,16250
|
|
45
49
|
test/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
50
|
test/api/test_bucketing_client.py,sha256=M2mjACowLvbsIjXdP-w8-fwY02xqv1X1r_h9v-pXa7A,7739
|
|
47
51
|
test/api/test_config_client.py,sha256=3BwMm4y-4NQcdW2DDGppoJLIF-ffgjlUJti2Qjw1D1M,5129
|
|
48
52
|
test/api/test_event_client.py,sha256=v4Xoum-PdywfczrfMV1llM5vrIJoqHybzxPLVokh09g,3310
|
|
49
|
-
test/api/test_local_bucketing.py,sha256=
|
|
53
|
+
test/api/test_local_bucketing.py,sha256=0cbD8kiRYCVadvU-ldMES-sr7rV9Ld4H1q62HCx4AHU,15970
|
|
50
54
|
test/fixture/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
55
|
test/fixture/data.py,sha256=6ReLxWPMhCDbJ5Ex24_iR0PJNjKzPFV1I9j_v0FVbBU,1462
|
|
52
56
|
test/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -54,15 +58,15 @@ test/managers/test_config_manager.py,sha256=2TUnt8501KM7UlJNH7srIhvC-izehD7nOfqZ
|
|
|
54
58
|
test/managers/test_event_queue_manager.py,sha256=z850atk8zAlD7sYaA1OJwgCFcfC0ps4NEk4XUnNCq1U,11629
|
|
55
59
|
test/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
60
|
test/models/test_bucketed_config.py,sha256=8wCEyxaHxY21nl7ZbiFzp-IzZQBZIPIVPPzeREjumQk,858
|
|
57
|
-
test/models/test_user.py,sha256=
|
|
61
|
+
test/models/test_user.py,sha256=ZUbFUndYrnefyGl8rxZgG3HdHPZs4BosQWimkT7etJc,10540
|
|
58
62
|
test/openfeature_test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
test/openfeature_test/test_provider.py,sha256=
|
|
60
|
-
test/openfeature_test/test_provider_local_sdk.py,sha256=
|
|
63
|
+
test/openfeature_test/test_provider.py,sha256=hIzdqqBTulGRODeTcRJUP93v76WEolUC2QRe3DccF3U,10932
|
|
64
|
+
test/openfeature_test/test_provider_local_sdk.py,sha256=ExkA1LYLuvW-dD4Bw2BKggzDQ8GpnIp3WyNK4rUZgJQ,5696
|
|
61
65
|
test/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
66
|
test/util/test_strings.py,sha256=T5H5U0af7_ld1yJC8IdDmay_Mx-iJQ5Fi5fbvKcAc7A,862
|
|
63
67
|
test/util/test_utils.py,sha256=tVBJm_qnqg-4PssLpXIxqlk0JehuiAIPs4zpi2oNVnY,6671
|
|
64
68
|
test/util/test_version.py,sha256=3Xg0_84m0bdHXz6pxd2Z85Oz9DoUC1T0Ol_WqEH_jac,335
|
|
65
|
-
devcycle_python_server_sdk-3.
|
|
66
|
-
devcycle_python_server_sdk-3.
|
|
67
|
-
devcycle_python_server_sdk-3.
|
|
68
|
-
devcycle_python_server_sdk-3.
|
|
69
|
+
devcycle_python_server_sdk-3.12.0.dist-info/METADATA,sha256=-bA66ayqIdC5UFrsLx0jZ9m4eNSHzcdTuFvA-sY-IQE,723
|
|
70
|
+
devcycle_python_server_sdk-3.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
71
|
+
devcycle_python_server_sdk-3.12.0.dist-info/top_level.txt,sha256=34f8zDzihAHoH7siAFlmscyO_QLNWWq9HApFlwtYL4k,33
|
|
72
|
+
devcycle_python_server_sdk-3.12.0.dist-info/RECORD,,
|
test/api/test_local_bucketing.py
CHANGED
|
@@ -10,6 +10,7 @@ from devcycle_python_sdk.models.bucketed_config import (
|
|
|
10
10
|
Project,
|
|
11
11
|
ProjectSettings,
|
|
12
12
|
)
|
|
13
|
+
from devcycle_python_sdk.models.eval_reason import EvalReason
|
|
13
14
|
from devcycle_python_sdk.models.feature import Feature
|
|
14
15
|
from devcycle_python_sdk.models.variable import Variable
|
|
15
16
|
from devcycle_python_sdk.models.platform_data import default_platform_data
|
|
@@ -155,6 +156,11 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
155
156
|
evalReason=None,
|
|
156
157
|
)
|
|
157
158
|
}
|
|
159
|
+
expected_eval = EvalReason(
|
|
160
|
+
reason="TARGETING_MATCH",
|
|
161
|
+
details="All Users",
|
|
162
|
+
target_id="63125321d31c601f992288bc",
|
|
163
|
+
)
|
|
158
164
|
expected_variables = {
|
|
159
165
|
"a-cool-new-feature": Variable(
|
|
160
166
|
_id="62fbf6566f1ba302829f9e34",
|
|
@@ -164,6 +170,7 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
164
170
|
isDefaulted=None,
|
|
165
171
|
defaultValue=None,
|
|
166
172
|
evalReason=None,
|
|
173
|
+
eval=expected_eval,
|
|
167
174
|
),
|
|
168
175
|
"string-var": Variable(
|
|
169
176
|
_id="63125320a4719939fd57cb2b",
|
|
@@ -173,6 +180,7 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
173
180
|
isDefaulted=None,
|
|
174
181
|
defaultValue=None,
|
|
175
182
|
evalReason=None,
|
|
183
|
+
eval=expected_eval,
|
|
176
184
|
),
|
|
177
185
|
"json-var": Variable(
|
|
178
186
|
_id="64372363125123fca69d3f7b",
|
|
@@ -186,6 +194,7 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
186
194
|
isDefaulted=None,
|
|
187
195
|
defaultValue=None,
|
|
188
196
|
evalReason=None,
|
|
197
|
+
eval=expected_eval,
|
|
189
198
|
),
|
|
190
199
|
"num-var": Variable(
|
|
191
200
|
_id="65272363125123fca69d3a7d",
|
|
@@ -195,6 +204,7 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
195
204
|
isDefaulted=None,
|
|
196
205
|
defaultValue=None,
|
|
197
206
|
evalReason=None,
|
|
207
|
+
eval=expected_eval,
|
|
198
208
|
),
|
|
199
209
|
"float-var": Variable(
|
|
200
210
|
_id="61200363125123fca69d3a7a",
|
|
@@ -204,6 +214,7 @@ class LocalBucketingTest(unittest.TestCase):
|
|
|
204
214
|
isDefaulted=None,
|
|
205
215
|
defaultValue=None,
|
|
206
216
|
evalReason=None,
|
|
217
|
+
eval=expected_eval,
|
|
207
218
|
),
|
|
208
219
|
}
|
|
209
220
|
|
test/models/test_user.py
CHANGED
|
@@ -53,6 +53,96 @@ class DevCycleUserTest(unittest.TestCase):
|
|
|
53
53
|
self.assertIsNotNone(user)
|
|
54
54
|
self.assertEqual(user.user_id, test_user_id)
|
|
55
55
|
|
|
56
|
+
def test_create_user_from_context_with_user_id_attribute(self):
|
|
57
|
+
"""Comprehensive test for userId attribute support including priority, functionality, and error cases"""
|
|
58
|
+
targeting_key_id = "targeting-12345"
|
|
59
|
+
user_id = "user_id-12345"
|
|
60
|
+
user_id_attr = "userId-12345"
|
|
61
|
+
|
|
62
|
+
# Test 1: userId as the only user ID source
|
|
63
|
+
context = EvaluationContext(
|
|
64
|
+
targeting_key=None, attributes={"userId": user_id_attr}
|
|
65
|
+
)
|
|
66
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
67
|
+
self.assertIsNotNone(user)
|
|
68
|
+
self.assertEqual(user.user_id, user_id_attr)
|
|
69
|
+
|
|
70
|
+
# Test 2: Priority order - targeting_key > user_id > userId
|
|
71
|
+
context = EvaluationContext(
|
|
72
|
+
targeting_key=targeting_key_id,
|
|
73
|
+
attributes={"user_id": user_id, "userId": user_id_attr},
|
|
74
|
+
)
|
|
75
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
76
|
+
self.assertEqual(user.user_id, targeting_key_id)
|
|
77
|
+
|
|
78
|
+
context = EvaluationContext(
|
|
79
|
+
targeting_key=None, attributes={"user_id": user_id, "userId": user_id_attr}
|
|
80
|
+
)
|
|
81
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
82
|
+
self.assertEqual(user.user_id, user_id)
|
|
83
|
+
|
|
84
|
+
# Test 3: Error cases - invalid userId types
|
|
85
|
+
with self.assertRaises(TargetingKeyMissingError):
|
|
86
|
+
DevCycleUser.create_user_from_context(
|
|
87
|
+
EvaluationContext(targeting_key=None, attributes={"userId": 12345})
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
with self.assertRaises(TargetingKeyMissingError):
|
|
91
|
+
DevCycleUser.create_user_from_context(
|
|
92
|
+
EvaluationContext(targeting_key=None, attributes={"userId": None})
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def test_create_user_from_context_user_id_exclusion(self):
|
|
96
|
+
"""Test that all user ID fields (targeting_key, user_id, userId) are excluded from custom data"""
|
|
97
|
+
targeting_key_id = "targeting-12345"
|
|
98
|
+
user_id = "user_id-12345"
|
|
99
|
+
user_id_attr = "userId-12345"
|
|
100
|
+
|
|
101
|
+
# Test exclusion when targeting_key is used
|
|
102
|
+
context = EvaluationContext(
|
|
103
|
+
targeting_key=targeting_key_id,
|
|
104
|
+
attributes={
|
|
105
|
+
"user_id": user_id,
|
|
106
|
+
"userId": user_id_attr,
|
|
107
|
+
"targeting_key": "should-be-excluded",
|
|
108
|
+
"other_field": "value",
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
112
|
+
self.assertEqual(user.user_id, targeting_key_id)
|
|
113
|
+
self.assertIsNotNone(user.customData)
|
|
114
|
+
self.assertNotIn("user_id", user.customData)
|
|
115
|
+
self.assertNotIn("userId", user.customData)
|
|
116
|
+
self.assertNotIn("targeting_key", user.customData)
|
|
117
|
+
self.assertEqual(user.customData["other_field"], "value")
|
|
118
|
+
|
|
119
|
+
# Test exclusion when user_id is used
|
|
120
|
+
context = EvaluationContext(
|
|
121
|
+
targeting_key=None,
|
|
122
|
+
attributes={
|
|
123
|
+
"user_id": user_id,
|
|
124
|
+
"userId": user_id_attr,
|
|
125
|
+
"other_field": "value",
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
129
|
+
self.assertEqual(user.user_id, user_id)
|
|
130
|
+
self.assertIsNotNone(user.customData)
|
|
131
|
+
self.assertNotIn("user_id", user.customData)
|
|
132
|
+
self.assertNotIn("userId", user.customData)
|
|
133
|
+
self.assertEqual(user.customData["other_field"], "value")
|
|
134
|
+
|
|
135
|
+
# Test exclusion when userId is used
|
|
136
|
+
context = EvaluationContext(
|
|
137
|
+
targeting_key=None,
|
|
138
|
+
attributes={"userId": user_id_attr, "other_field": "value"},
|
|
139
|
+
)
|
|
140
|
+
user = DevCycleUser.create_user_from_context(context)
|
|
141
|
+
self.assertEqual(user.user_id, user_id_attr)
|
|
142
|
+
self.assertIsNotNone(user.customData)
|
|
143
|
+
self.assertNotIn("userId", user.customData)
|
|
144
|
+
self.assertEqual(user.customData["other_field"], "value")
|
|
145
|
+
|
|
56
146
|
def test_create_user_from_context_with_attributes(self):
|
|
57
147
|
test_user_id = "12345"
|
|
58
148
|
context = EvaluationContext(
|