FeatureManagement 2.0.0b1__tar.gz → 2.0.0b2__tar.gz
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.
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/CHANGELOG.md +5 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2/FeatureManagement.egg-info}/PKG-INFO +1 -1
- {featuremanagement-2.0.0b1/FeatureManagement.egg-info → featuremanagement-2.0.0b2}/PKG-INFO +1 -1
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featuremanagerbase.py +6 -3
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_allocation.py +5 -5
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_feature_flag.py +2 -4
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_version.py +1 -1
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/azuremonitor/_send_telemetry.py +38 -4
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/pyproject.toml +1 -1
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_variants.py +40 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/CODE_OF_CONDUCT.md +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/SOURCES.txt +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/dependency_links.txt +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/not-zip-safe +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/requires.txt +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/top_level.txt +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/LICENSE +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/MANIFEST.in +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/README.md +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/SECURITY.md +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/SUPPORT.md +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/__init__.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_defaultfilters.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featurefilters.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featuremanager.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/__init__.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_constants.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_evaluation_event.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_feature_conditions.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_targeting_context.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_telemetry.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_variant.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_variant_assignment_reason.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_variant_reference.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/__init__.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_defaultfilters.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_featurefilters.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_featuremanager.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/azuremonitor/__init__.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/py.typed +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/feature_flag_sample.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/feature_flag_with_azure_app_configuration_sample.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/feature_variant_sample.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/feature_variant_sample_with_telemetry.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/formatted_feature_flags.json +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/random_filter.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/setup.cfg +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/setup.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_default_feature_flags.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_default_feature_flags_async.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_manager.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_manager_async.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_manager_refresh.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_variants_async.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_send_telemetry_appinsights.py +0 -0
- {featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/validation_tests/test_json_validations.py +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 2.0.0b2 (10/11/2024)
|
|
4
|
+
|
|
5
|
+
* Adds VariantAllocationPercentage, DefaultWhenEnabled, and AllocationId to telemetry.
|
|
6
|
+
* Allocation seed value is now None by default, and only defaults to `allocation\n<feature.id>` when assigning variants.
|
|
7
|
+
|
|
3
8
|
## 2.0.0b1 (09/10/2024)
|
|
4
9
|
|
|
5
10
|
* Adds support for Feature Variants.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: FeatureManagement
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b2
|
|
4
4
|
Summary: A library for enabling/disabling features at runtime.
|
|
5
5
|
Home-page: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/feature-management
|
|
6
6
|
Author: Microsoft Corporation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: FeatureManagement
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b2
|
|
4
4
|
Summary: A library for enabling/disabling features at runtime.
|
|
5
5
|
Home-page: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/feature-management
|
|
6
6
|
Author: Microsoft Corporation
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featuremanagerbase.py
RENAMED
|
@@ -168,14 +168,17 @@ class FeatureManagerBase(ABC):
|
|
|
168
168
|
if targeting_context.user_id in user_allocation.users:
|
|
169
169
|
evaluation_event.reason = VariantAssignmentReason.USER
|
|
170
170
|
variant_name = user_allocation.variant
|
|
171
|
-
|
|
171
|
+
if not variant_name and feature.allocation.group and len(targeting_context.groups) > 0:
|
|
172
172
|
for group_allocation in feature.allocation.group:
|
|
173
173
|
for group in targeting_context.groups:
|
|
174
174
|
if group in group_allocation.groups:
|
|
175
175
|
evaluation_event.reason = VariantAssignmentReason.GROUP
|
|
176
176
|
variant_name = group_allocation.variant
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
if not variant_name and feature.allocation.percentile:
|
|
178
|
+
seed = feature.allocation.seed
|
|
179
|
+
if not seed:
|
|
180
|
+
seed = "allocation\n" + feature.name
|
|
181
|
+
context_id = targeting_context.user_id + "\n" + seed
|
|
179
182
|
box: float = self._is_targeted(context_id)
|
|
180
183
|
for percentile_allocation in feature.allocation.percentile:
|
|
181
184
|
if box == 100 and percentile_allocation.percentile_to == 100:
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_allocation.py
RENAMED
|
@@ -103,16 +103,16 @@ class Allocation:
|
|
|
103
103
|
Represents an allocation configuration for a feature flag.
|
|
104
104
|
"""
|
|
105
105
|
|
|
106
|
-
def __init__(self
|
|
106
|
+
def __init__(self) -> None:
|
|
107
107
|
self._default_when_enabled = None
|
|
108
108
|
self._default_when_disabled = None
|
|
109
109
|
self._user: List[UserAllocation] = []
|
|
110
110
|
self._group: List[GroupAllocation] = []
|
|
111
111
|
self._percentile: List[PercentileAllocation] = []
|
|
112
|
-
self._seed =
|
|
112
|
+
self._seed = None
|
|
113
113
|
|
|
114
114
|
@classmethod
|
|
115
|
-
def convert_from_json(cls, json: Dict[str, Any]
|
|
115
|
+
def convert_from_json(cls, json: Dict[str, Any]) -> Optional["Allocation"]:
|
|
116
116
|
"""
|
|
117
117
|
Convert a JSON object to Allocation.
|
|
118
118
|
|
|
@@ -123,7 +123,7 @@ class Allocation:
|
|
|
123
123
|
"""
|
|
124
124
|
if not json:
|
|
125
125
|
return None
|
|
126
|
-
allocation = cls(
|
|
126
|
+
allocation = cls()
|
|
127
127
|
allocation._default_when_enabled = json.get(DEFAULT_WHEN_ENABLED)
|
|
128
128
|
allocation._default_when_disabled = json.get(DEFAULT_WHEN_DISABLED)
|
|
129
129
|
allocation._user = []
|
|
@@ -197,7 +197,7 @@ class Allocation:
|
|
|
197
197
|
return self._percentile
|
|
198
198
|
|
|
199
199
|
@property
|
|
200
|
-
def seed(self) -> str:
|
|
200
|
+
def seed(self) -> Optional[str]:
|
|
201
201
|
"""
|
|
202
202
|
Get the seed for the allocation.
|
|
203
203
|
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_feature_flag.py
RENAMED
|
@@ -51,9 +51,7 @@ class FeatureFlag:
|
|
|
51
51
|
)
|
|
52
52
|
else:
|
|
53
53
|
feature_flag._conditions = FeatureConditions()
|
|
54
|
-
feature_flag._allocation = Allocation.convert_from_json(
|
|
55
|
-
json_value.get(FEATURE_FLAG_ALLOCATION, None), feature_flag._id
|
|
56
|
-
)
|
|
54
|
+
feature_flag._allocation = Allocation.convert_from_json(json_value.get(FEATURE_FLAG_ALLOCATION, None))
|
|
57
55
|
if FEATURE_FLAG_VARIANTS in json_value:
|
|
58
56
|
variants: List[Mapping[str, Any]] = json_value.get(FEATURE_FLAG_VARIANTS, [])
|
|
59
57
|
feature_flag._variants = []
|
|
@@ -66,7 +64,7 @@ class FeatureFlag:
|
|
|
66
64
|
return feature_flag
|
|
67
65
|
|
|
68
66
|
@property
|
|
69
|
-
def name(self) ->
|
|
67
|
+
def name(self) -> str:
|
|
70
68
|
"""
|
|
71
69
|
Get the name of the feature flag.
|
|
72
70
|
|
|
@@ -25,6 +25,8 @@ REASON = "VariantAssignmentReason"
|
|
|
25
25
|
|
|
26
26
|
EVENT_NAME = "FeatureEvaluation"
|
|
27
27
|
|
|
28
|
+
EVALUATION_EVENT_VERSION = "1.0.0"
|
|
29
|
+
|
|
28
30
|
|
|
29
31
|
def track_event(event_name: str, user: str, event_properties: Optional[Dict[str, Optional[str]]] = None) -> None:
|
|
30
32
|
"""
|
|
@@ -51,17 +53,49 @@ def publish_telemetry(evaluation_event: EvaluationEvent) -> None:
|
|
|
51
53
|
"""
|
|
52
54
|
if not HAS_AZURE_MONITOR_EVENTS_EXTENSION:
|
|
53
55
|
return
|
|
54
|
-
event = {}
|
|
55
|
-
if evaluation_event.feature:
|
|
56
|
-
|
|
56
|
+
event: Dict[str, Optional[str]] = {}
|
|
57
|
+
if not evaluation_event.feature:
|
|
58
|
+
return
|
|
59
|
+
event[FEATURE_NAME] = evaluation_event.feature.name
|
|
57
60
|
event[ENABLED] = str(evaluation_event.enabled)
|
|
61
|
+
event["Version"] = EVALUATION_EVENT_VERSION
|
|
58
62
|
|
|
63
|
+
# VariantAllocationPercentage
|
|
59
64
|
if evaluation_event.reason and evaluation_event.reason != VariantAssignmentReason.NONE:
|
|
60
65
|
if evaluation_event.variant:
|
|
61
66
|
event[VARIANT] = evaluation_event.variant.name
|
|
62
67
|
event[REASON] = evaluation_event.reason.value
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
if evaluation_event.reason == VariantAssignmentReason.DEFAULT_WHEN_ENABLED:
|
|
70
|
+
allocation_percentage = 0
|
|
71
|
+
|
|
72
|
+
if evaluation_event.feature.allocation and evaluation_event.feature.allocation.percentile:
|
|
73
|
+
for allocation in evaluation_event.feature.allocation.percentile:
|
|
74
|
+
if (
|
|
75
|
+
evaluation_event.variant
|
|
76
|
+
and allocation.variant == evaluation_event.variant.name
|
|
77
|
+
and allocation.percentile_to
|
|
78
|
+
):
|
|
79
|
+
allocation_percentage += allocation.percentile_to - allocation.percentile_from
|
|
80
|
+
|
|
81
|
+
event["VariantAssignmentPercentage"] = str(100 - allocation_percentage)
|
|
82
|
+
elif evaluation_event.reason == VariantAssignmentReason.PERCENTILE:
|
|
83
|
+
if evaluation_event.feature.allocation and evaluation_event.feature.allocation.percentile:
|
|
84
|
+
allocation_percentage = 0
|
|
85
|
+
for allocation in evaluation_event.feature.allocation.percentile:
|
|
86
|
+
if (
|
|
87
|
+
evaluation_event.variant
|
|
88
|
+
and allocation.variant == evaluation_event.variant.name
|
|
89
|
+
and allocation.percentile_to
|
|
90
|
+
):
|
|
91
|
+
allocation_percentage += allocation.percentile_to - allocation.percentile_from
|
|
92
|
+
event["VariantAssignmentPercentage"] = str(allocation_percentage)
|
|
93
|
+
|
|
94
|
+
# DefaultWhenEnabled
|
|
95
|
+
if evaluation_event.feature.allocation and evaluation_event.feature.allocation.default_when_enabled:
|
|
96
|
+
event["DefaultWhenEnabled"] = evaluation_event.feature.allocation.default_when_enabled
|
|
97
|
+
|
|
98
|
+
if evaluation_event.feature.telemetry:
|
|
65
99
|
for metadata_key, metadata_value in evaluation_event.feature.telemetry.metadata.items():
|
|
66
100
|
if metadata_key not in event:
|
|
67
101
|
event[metadata_key] = metadata_value
|
|
@@ -112,6 +112,46 @@ class TestFeatureVariants:
|
|
|
112
112
|
assert feature_manager.is_enabled("Alpha", "Charlie")
|
|
113
113
|
assert feature_manager.get_variant("Alpha", "Charlie") is None
|
|
114
114
|
|
|
115
|
+
def test_user_and_group_allocation(self):
|
|
116
|
+
feature_flags = {
|
|
117
|
+
"feature_management": {
|
|
118
|
+
"feature_flags": [
|
|
119
|
+
{
|
|
120
|
+
"id": "Alpha",
|
|
121
|
+
"enabled": True,
|
|
122
|
+
"variants": [
|
|
123
|
+
{"name": "Off", "status_override": "Enabled"},
|
|
124
|
+
{"name": "On", "status_override": "Disabled"},
|
|
125
|
+
],
|
|
126
|
+
"allocation": {
|
|
127
|
+
"user": [{"variant": "On", "users": ["Adam"]}, {"variant": "Off", "users": ["Brittney"]}],
|
|
128
|
+
"group": [
|
|
129
|
+
{"variant": "On", "groups": ["Group1"]},
|
|
130
|
+
{"variant": "Off", "groups": ["Group2"]},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
"conditions": {
|
|
134
|
+
"client_filters": [
|
|
135
|
+
{
|
|
136
|
+
"name": "AlwaysOnFilter",
|
|
137
|
+
"parameters": {},
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
feature_manager = FeatureManager(feature_flags, feature_filters=[AlwaysOnFilter()])
|
|
146
|
+
assert feature_manager.is_enabled("Alpha")
|
|
147
|
+
assert feature_manager.get_variant("Alpha") is None
|
|
148
|
+
assert not feature_manager.is_enabled("Alpha", TargetingContext(user_id="NotAdam", groups=["Group1"]))
|
|
149
|
+
assert feature_manager.get_variant("Alpha", TargetingContext(user_id="NotAdam", groups=["Group1"])).name == "On"
|
|
150
|
+
assert not feature_manager.is_enabled("Alpha", TargetingContext(user_id="NotAdam", groups=["Group1"]))
|
|
151
|
+
assert feature_manager.get_variant("Alpha", TargetingContext(groups=["Group2"])).name == "Off"
|
|
152
|
+
assert feature_manager.is_enabled("Alpha", TargetingContext(user_id="NotCharlie", groups=["Group3"]))
|
|
153
|
+
assert feature_manager.get_variant("Alpha", TargetingContext(user_id="NotCharlie", groups=["Group3"])) is None
|
|
154
|
+
|
|
115
155
|
# method: is_enabled
|
|
116
156
|
def test_basic_feature_variant_allocation_groups(self):
|
|
117
157
|
feature_flags = {
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/requires.txt
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/FeatureManagement.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_defaultfilters.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featurefilters.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_featuremanager.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/__init__.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_telemetry.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/_models/_variant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_defaultfilters.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_featurefilters.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/aio/_featuremanager.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/featuremanagement/azuremonitor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/samples/formatted_feature_flags.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_default_feature_flags_async.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_manager_refresh.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_feature_variants_async.py
RENAMED
|
File without changes
|
{featuremanagement-2.0.0b1 → featuremanagement-2.0.0b2}/tests/test_send_telemetry_appinsights.py
RENAMED
|
File without changes
|
|
File without changes
|