Skip to content

Commit f3b3414

Browse files
committed
Merge branch 'main' into gh-pages
2 parents 1ac7c08 + c497ab7 commit f3b3414

6 files changed

Lines changed: 44 additions & 267 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
11
# Release History
22

3-
## 1.0.0b1 (Unreleased)
3+
## 1.0.0 (06/26/2024)
4+
5+
Updated version to 1.0.0.
6+
7+
## 1.0.0b1 (05/22/2024)
8+
9+
New Feature Management library.
10+
11+
Provides the ability to manage feature flags in a project. Enables:
12+
13+
* Loading of feature flags from a file, see: https://github.com/Azure/AppConfiguration/blob/main/docs/FeatureManagement/FeatureManagement.v2.0.0.schema.json
14+
* Loading of feature flags from Azure App Configuration.
15+
* Checking if a feature is enabled.
16+
* Default feature filters: TimeWindowFilter, TargetingFilter.
17+
* Custom feature filters.

README.md

Lines changed: 10 additions & 262 deletions
Original file line numberDiff line numberDiff line change
@@ -1,271 +1,21 @@
11
# Microsoft Feature Management for Python
22

3-
Feature Management is a library for enabling/disabling features at runtime. Developers can use feature flags in simple use cases like conditional statement to more advanced scenarios like conditionally adding routes.
3+
[![FeatureManagement](https://img.shields.io/pypi/v/FeatureManagement?label=FeatureManagement)](https://pypi.org/project/FeatureManagement/)
44

5-
## Getting started
5+
Feature management provides a way to develop and expose application functionality based on features. Many applications have special requirements when a new feature is developed such as when the feature should be enabled and under what conditions. This library provides a way to define these relationships, and also integrates into common Python code patterns to make exposing these features possible.
66

7-
### Prerequisites
7+
## Get Started
88

9-
* Python 3.7 or later is required to use this package.
9+
[Quickstart](https://learn.microsoft.com/azure/azure-app-configuration/quickstart-feature-flag-python): A quickstart guide is available to learn how to integrate feature flags from Azure App Configuration into your Python applications.
1010

11-
### Install the package
11+
[API Reference](https://microsoft.github.io/FeatureManagement-Python/): This API reference details the API surface of the libraries contained within this repository.
1212

13-
Install the Python feature management client library for Python with [pip][pip]:
13+
## Examples
1414

15-
```bash
16-
pip install featuremanagement
17-
```
18-
19-
## Usage
20-
21-
You can use feature flags from the Azure App Configuration service, a json file, or a dictionary.
22-
23-
### Use feature flags from Azure App Configuration
24-
25-
```python
26-
from featuremanagement import FeatureManager
27-
from azure.appconfiguration.provider import load
28-
from azure.identity import DefaultAzureCredential
29-
import os
30-
31-
endpoint = os.environ.get("APPCONFIGURATION_ENDPOINT_STRING")
32-
33-
config = load(endpoint=endpoint, credential=DefaultAzureCredential(), feature_flag_enabled=True, feature_flag_refresh_enabled=True)
34-
35-
feature_manager = FeatureManager(config)
36-
37-
# Prints the value of the feature flag Alpha
38-
print("Alpha is ", feature_manager.is_enabled("Alpha"))
39-
```
40-
41-
### Use feature flags from a json file
42-
43-
A Json file with the following format can be used to load feature flags.
44-
45-
```json
46-
{
47-
"feature_management": {
48-
"feature_flags": [
49-
{
50-
"id": "Alpha",
51-
"description": "",
52-
"enabled": "true",
53-
"conditions": {
54-
"client_filters": []
55-
}
56-
}
57-
]
58-
}
59-
}
60-
```
61-
62-
Load feature flags from a json file.
63-
64-
```python
65-
from featuremanagement import FeatureManager
66-
import json
67-
import os
68-
import sys
69-
70-
script_directory = os.path.dirname(os.path.abspath(sys.argv[0]))
71-
72-
f = open(script_directory + "/my_json_file.json", "r")
73-
74-
feature_flags = json.load(f)
75-
76-
feature_manager = FeatureManager(feature_flags)
77-
78-
# Returns the value of Alpha, based on the result of the feature filter
79-
print("Alpha is ", feature_manager.is_enabled("Alpha"))
80-
```
81-
82-
### Use feature flags from a dictionary
83-
84-
```python
85-
from featuremanagement import FeatureManager
86-
87-
feature_flags = {
88-
"feature_management": {
89-
"feature_flags": [
90-
{
91-
"id": "Alpha",
92-
"description": "",
93-
"enabled": "true",
94-
"conditions": {
95-
"client_filters": []
96-
}
97-
}
98-
]
99-
}
100-
}
101-
102-
feature_manager = FeatureManager(feature_flags)
103-
104-
# Is always true
105-
print("Alpha is ", feature_manager.is_enabled("Alpha"))
106-
```
107-
108-
## Key concepts
109-
110-
### FeatureManager
111-
112-
The `FeatureManager` is the main entry point for using feature flags. It is initialized with a dictionary of feature flags, and optional feature filters. The `FeatureManager` can then be used to check if a feature is enabled or disabled.
113-
114-
### Feature Flags
115-
116-
Feature Flags are objects that define how Feature Management enables/disables a feature. It contains an `id` and `enabled` property. The `id` is a string that uniquely identifies the feature flag. The `enabled` property is a boolean that indicates if the feature flag is enabled or disabled. The `conditions` object contains a property `client_filters` which is a list of `FeatureFilter` objects that are used to determine if the feature flag is enabled or disabled. The Feature Filters only run if the feature flag is enabled.
117-
118-
The full schema for a feature Flag can be found [here](https://github.com/Azure/AppConfiguration/blob/main/docs/FeatureManagement/FeatureFlag.v1.1.0.schema.json).
119-
120-
```javascript
121-
{
122-
"id": "Alpha",
123-
"enabled": "true",
124-
"conditions": {
125-
"client_filters": [
126-
{
127-
"name": "MyFilter",
128-
"parameters": {
129-
...
130-
}
131-
}
132-
]
133-
}
134-
}
135-
```
136-
137-
This object is passed into the `FeatureManager` when it is initialized.
138-
139-
### Feature Filters
140-
141-
Feature filters enable dynamic evaluation of feature flags. The Python feature management library includes two built-in filters:
142-
143-
- `Microsoft.TimeWindow` - Enables a feature flag based on a time window.
144-
- `Microsoft.Targeting` - Enables a feature flag based on a list of users, groups, or rollout percentages.
145-
146-
#### Time Window Filter
147-
148-
The Time Window Filter enables a feature flag based on a time window. It has two parameters:
149-
150-
- `Start` - The start time of the time window.
151-
- `End` - The end time of the time window.
152-
153-
```json
154-
{
155-
"name": "Microsoft.TimeWindow",
156-
"parameters": {
157-
"Start": "2020-01-01T00:00:00Z",
158-
"End": "2020-12-31T00:00:00Z"
159-
}
160-
}
161-
```
162-
163-
Both parameters are optional, but at least one is required. The time window filter is enabled after the start time and before the end time. If the start time is not specified, it is enabled immediately. If the end time is not specified, it will remain enabled after the start time.
164-
165-
#### Targeting Filter
166-
167-
Targeting is a feature management strategy that enables developers to progressively roll out new features to their user base. The strategy is built on the concept of targeting a set of users known as the target audience. An audience is made up of specific users, groups, excluded users/groups, and a designated percentage of the entire user base. The groups that are included in the audience can be broken down further into percentages of their total members.
168-
169-
The following steps demonstrate an example of a progressive rollout for a new 'Beta' feature:
170-
171-
1. Individual users Jeff and Alicia are granted access to the Beta
172-
1. Another user, Mark, asks to opt-in and is included.
173-
1. Twenty percent of a group known as "Ring1" users are included in the Beta.
174-
1. The number of "Ring1" users included in the beta is bumped up to 100 percent.
175-
1. Five percent of the user base is included in the beta.
176-
1. The rollout percentage is bumped up to 100 percent and the feature is completely rolled out.
177-
178-
This strategy for rolling out a feature is built in to the library through the included Microsoft.Targeting feature filter.
179-
180-
##### Defining a Targeting Feature Filter
181-
182-
The Targeting Filter provides the capability to enable a feature for a target audience. The filter parameters include an `Audience` object which describes users, groups, excluded users/groups, and a default percentage of the user base that should have access to the feature. The `Audience` object contains the following fields:
183-
184-
- `Users` - A list of users that the feature flag is enabled for.
185-
- `Groups` - A list of groups that the feature flag is enabled for and a rollout percentage for each group.
186-
- `Name` - The name of the group.
187-
- `RolloutPercentage` - A percentage value that the feature flag is enabled for in the given group.
188-
- `DefaultRolloutPercentage` - A percentage value that the feature flag is enabled for.
189-
- `Exclusion` - An object that contains a list of users and groups that the feature flag is disabled for.
190-
- `Users` - A list of users that the feature flag is disabled for.
191-
- `Groups` - A list of groups that the feature flag is disabled for.
192-
193-
```json
194-
{
195-
"name": "Microsoft.Targeting",
196-
"parameters": {
197-
"Audience": {
198-
"Users": ["user1", "user2"],
199-
"Groups": [
200-
{
201-
"Name": "group1",
202-
"RolloutPercentage": 100
203-
}
204-
],
205-
"DefaultRolloutPercentage": 50,
206-
"Exclusion": {
207-
"Users": ["user3"],
208-
"Groups": ["group2"]
209-
}
210-
}
211-
}
212-
}
213-
```
214-
215-
##### Using Targeting Feature Filter
216-
217-
You can provide the current user info through `kwargs` when calling `isEnabled`.
218-
219-
```python
220-
from featuremanagement import FeatureManager, TargetingContext
221-
222-
# Returns true, because user1 is in the Users list
223-
feature_manager.is_enabled("Beta", TargetingContext(user_id="user1", groups=["group1"]))
224-
225-
# Returns false, because group2 is in the Exclusion.Groups list
226-
feature_manager.is_enabled("Beta", TargetingContext(user_id="user1", groups=["group2"]))
227-
228-
# Has a 50% chance of returning true, but will be conisistent for the same user
229-
feature_manager.is_enabled("Beta", TargetingContext(user_id="user4"))
230-
```
231-
232-
#### Custom Filters
233-
234-
You can also create your own feature filters by implementing the `FeatureFilter` interface.
235-
236-
```python
237-
class MyCustomFilter(FeatureFilter):
238-
239-
def evaluate(self, context, **kwargs):
240-
...
241-
return True
242-
```
243-
244-
They can then be passed into the `FeatureManager` when it is initialized. By default, the name of a feature filter is the name of the class. You can override this by setting a class attribute `alias` to the modified class name.
245-
246-
```python
247-
248-
feature_manager = FeatureManager(feature_flags, feature_filters={MyCustomFilter(), MyOtherFilter()})
249-
```
250-
251-
The `evaluate` method is called when checking if a feature flag is enabled. The `context` parameter contains information about the feature filter from the `parameters` field of the feature filter. Any additional parameters can be passed in as keyword arguments when calling `is_enabled`.
252-
253-
```javascript
254-
{
255-
"name": "CustomFilter",
256-
"parameters": {
257-
...
258-
}
259-
}
260-
```
261-
262-
You can modify the name of a feature flag by using the `@FeatureFilter.alias` decorator. The alias overrides the name of the feature filter and needs to match the name of the feature filter in the feature flag json.
263-
264-
```python
265-
@FeatureFilter.alias("AliasFilter")
266-
class MyCustomFilter(FeatureFilter):
267-
...
268-
```
15+
* [Python Application](https://github.com/microsoft/FeatureManagement-Python/blob/main/samples/feature_flag_sample.py)
16+
* [Python Application with Azure App Configuration](https://github.com/microsoft/FeatureManagement-Python/blob/main/samples/feature_flag_with_azure_app_configuration_sample.py)
17+
* [Django Application](https://github.com/Azure/AppConfiguration/tree/main/examples/Python/python-django-webapp-sample)
18+
* [Flask Application](https://github.com/Azure/AppConfiguration/tree/main/examples/Python/python-flask-webapp-sample)
26919

27020
## Contributing
27121

@@ -288,5 +38,3 @@ trademarks or logos is subject to and must follow
28838
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
28939
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
29040
Any use of third-party trademarks or logos are subject to those third-party's policies.
291-
292-
[pip]: https://pypi.org/project/FeatureManagement/

dev_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ pylint
66
mypy
77
sphinx
88
sphinx_rtd_theme
9+
sphinx-toolbox
910
myst_parser
1011
azure-appconfiguration-provider

docs/conf.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414

1515
# -- General configuration ---------------------------------------------------
1616

17-
extensions = ["myst_parser", "sphinx.ext.autodoc", "sphinx.ext.coverage", "sphinx.ext.napoleon"]
17+
extensions = [
18+
"myst_parser",
19+
"sphinx.ext.autodoc",
20+
"sphinx.ext.coverage",
21+
"sphinx.ext.napoleon",
22+
"sphinx_toolbox.more_autodoc.autonamedtuple",
23+
]
1824

1925
templates_path = ["_templates"]
2026
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

featuremanagement/_models/_targeting_context.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,16 @@ class TargetingContext(NamedTuple):
1212
Represents the context for targeting a feature flag.
1313
"""
1414

15-
# The user ID
1615
user_id: str = ""
16+
"""
17+
The user ID.
18+
19+
:type: str
20+
"""
1721

18-
# The users groups
1922
groups: List[str] = []
23+
"""
24+
The users groups.
25+
26+
:type: List[str]
27+
"""

featuremanagement/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
# license information.
55
# -------------------------------------------------------------------------
66

7-
VERSION = "1.0.0b1"
7+
VERSION = "1.0.0"

0 commit comments

Comments
 (0)