Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Release History

## 2.5.1 (Unreleased)
## 2.6.0b1 (Unreleased)

### Features Added

- Feature flags created via the dedicated feature flag resource endpoint (`FeatureFlagClient`/`FeatureFlag` in `azure-appconfiguration`) are now loaded automatically alongside key-value based feature flags whenever `feature_flag_enabled=True`. Both kinds are merged into the same `feature_management.feature_flags` list, with resource-based feature flags taking precedence over key-value based ones when they share the same name. No new `load()` options are required to opt in, and existing `feature_flag_selectors` filter both kinds.

### Breaking Changes

- Raised the minimum supported Python version to 3.10, matching the minimum required by `azure-appconfiguration>=1.10.0b1`. Dropped support for Python 3.7, 3.8, and 3.9.

### Bugs Fixed

- Fixed a resource leak where replica clients that were no longer part of the auto-failover set were not closed during client refresh.
Expand All @@ -17,6 +21,7 @@
### Other Changes

- Bumped minimum dependency on `azure-core` to `>=1.31.0`.
- Bumped minimum dependency on `azure-appconfiguration` to `>=1.10.0b1` for `FeatureFlagClient`/`FeatureFlag` support.

## 2.5.0 (2026-05-22)

Expand Down
72 changes: 72 additions & 0 deletions sdk/appconfiguration/azure-appconfiguration-provider/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,72 @@ config = load(

<!-- END SNIPPET -->

### Loading Enhanced Feature Flags

Feature flags can also be created using the dedicated feature flag endpoint (via `FeatureFlagClient`/`FeatureFlag` in `azure-appconfiguration`), instead of as key-value configuration settings. These are referred to as enhanced feature flags. No additional `load()` options are required to load them — it happens automatically whenever `feature_flag_enabled=True`, and they are merged into the same `feature_management.feature_flags` list as key-value based feature flags, with enhanced feature flags taking precedence when both share the same name.

<!-- SNIPPET:enhanced_feature_flag_sample.enhanced_feature_flag_loading -->

```python
from azure.appconfiguration.provider import load

# Feature flags loaded from the enhanced feature flag endpoint are merged into the same
# feature_management.feature_flags list as key-value based feature flags.
config = load(endpoint=endpoint, credential=credential, feature_flag_enabled=True, **kwargs)
feature_flags = config["feature_management"]["feature_flags"]
enhanced_flag_beta = next(flag for flag in feature_flags if flag.get("id") == "EnhancedFeatureBeta")
print(enhanced_flag_beta["enabled"])
```

<!-- END SNIPPET -->

`FeatureFlagSelector` is the dedicated selector type for filtering enhanced feature flags by name, label, or tags, and is the recommended way to select enhanced feature flags.

<!-- SNIPPET:enhanced_feature_flag_sample.enhanced_feature_flag_selector_with_feature_flag_selector -->

```python
from azure.appconfiguration.provider import load, FeatureFlagSelector

# FeatureFlagSelector is the dedicated selector type for filtering enhanced feature flags.
config = load(
endpoint=endpoint,
credential=credential,
feature_flag_enabled=True,
feature_flag_selectors=[FeatureFlagSelector(name_filter="Enhanced*")],
**kwargs,
)
feature_flags = config["feature_management"]["feature_flags"]
enhanced_flag_beta = next(flag for flag in feature_flags if flag.get("id") == "EnhancedFeatureBeta")
print(enhanced_flag_beta["enabled"])
```

<!-- END SNIPPET -->

The same `SettingSelector` used to filter key-value based feature flags also filters enhanced feature flags, by name, label, or tags. A list of `feature_flag_selectors` must contain either `SettingSelector` or `FeatureFlagSelector` instances, but not both. Note that selectors with a `snapshot_name` are not currently supported for enhanced feature flags and are skipped when loading them.

<!-- SNIPPET:enhanced_feature_flag_sample.enhanced_feature_flag_selector -->

```python
from azure.appconfiguration.provider import load, SettingSelector

# The same SettingSelector used to filter key-value based feature flags also filters enhanced feature
# flags, by name/label/tags.
config = load(
endpoint=endpoint,
credential=credential,
feature_flag_enabled=True,
feature_flag_selectors=[SettingSelector(key_filter="Enhanced*")],
**kwargs,
)
feature_flags = config["feature_management"]["feature_flags"]
enhanced_flag_beta = next(flag for flag in feature_flags if flag.get("id") == "EnhancedFeatureBeta")
print(enhanced_flag_beta["enabled"])
```

<!-- END SNIPPET -->

Existing customers using key-value based feature flags do not need to make any code changes to benefit from this feature. If enhanced feature flags are created in the same App Configuration store, the provider will automatically load and merge them alongside the existing key-value based feature flags whenever `feature_flag_enabled=True`.

## JSON Content Type

Configuration settings with a JSON content type (e.g., `application/json`) are automatically deserialized into their corresponding Python objects when loaded by the provider.
Expand Down Expand Up @@ -469,6 +535,12 @@ This library uses the standard [logging](https://docs.python.org/3/library/loggi
* **Configuration not refreshing** — Make sure you are calling `config.refresh()` periodically (e.g., before each request in a web app). The provider does not auto-refresh in the background.
* **Startup failures** — If the store is unreachable during startup, the provider will retry until `startup_timeout` (default 100 seconds) is exceeded. Increase this value if your store is expected to have high latency.

## Testing

(This content is for `azure-appconfiguration-provider` package developer only)

See [tests/tests.md](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/appconfiguration/azure-appconfiguration-provider/tests/tests.md) for instructions on running unit and integration tests, working with recordings, and setting up environment variables for local testing.

## Next steps

Check out our Django and Flask examples to see how to use the provider in a web application.
Expand Down
19 changes: 15 additions & 4 deletions sdk/appconfiguration/azure-appconfiguration-provider/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace azure.appconfiguration.provider
*,
feature_flag_enabled: bool = False,
feature_flag_refresh_enabled: bool = False,
feature_flag_selectors: Optional[List[SettingSelector]] = ...,
feature_flag_selectors: Optional[Union[List[SettingSelector], List[FeatureFlagSelector]]] = ...,
key_vault_options: Optional[AzureAppConfigurationKeyVaultOptions] = ...,
keyvault_client_configs: Optional[Mapping[str, JSON]] = ...,
keyvault_credential: Optional[TokenCredential] = ...,
Expand All @@ -31,7 +31,7 @@ namespace azure.appconfiguration.provider
connection_string: str,
feature_flag_enabled: bool = False,
feature_flag_refresh_enabled: bool = False,
feature_flag_selectors: Optional[List[SettingSelector]] = ...,
feature_flag_selectors: Optional[Union[List[SettingSelector], List[FeatureFlagSelector]]] = ...,
key_vault_options: Optional[AzureAppConfigurationKeyVaultOptions] = ...,
keyvault_client_configs: Optional[Mapping[str, JSON]] = ...,
keyvault_credential: Optional[TokenCredential] = ...,
Expand Down Expand Up @@ -68,6 +68,17 @@ namespace azure.appconfiguration.provider
def refresh(self, **kwargs) -> None: ...


class azure.appconfiguration.provider.FeatureFlagSelector:

def __init__(
self,
*,
label_filter: Optional[str] = NULL_CHAR,
name_filter: Optional[str] = ...,
tag_filters: Optional[List[str]] = ...
): ...


class azure.appconfiguration.provider.SettingSelector:

def __init__(
Expand All @@ -94,7 +105,7 @@ namespace azure.appconfiguration.provider.aio
*,
feature_flag_enabled: bool = False,
feature_flag_refresh_enabled: bool = False,
feature_flag_selectors: Optional[List[SettingSelector]] = ...,
feature_flag_selectors: Optional[Union[List[SettingSelector], List[FeatureFlagSelector]]] = ...,
key_vault_options: Optional[AzureAppConfigurationKeyVaultOptions] = ...,
keyvault_client_configs: Optional[Mapping[str, JSON]] = ...,
keyvault_credential: Optional[AsyncTokenCredential] = ...,
Expand All @@ -117,7 +128,7 @@ namespace azure.appconfiguration.provider.aio
connection_string: str,
feature_flag_enabled: bool = False,
feature_flag_refresh_enabled: bool = False,
feature_flag_selectors: Optional[List[SettingSelector]] = ...,
feature_flag_selectors: Optional[Union[List[SettingSelector], List[FeatureFlagSelector]]] = ...,
key_vault_options: Optional[AzureAppConfigurationKeyVaultOptions] = ...,
keyvault_client_configs: Optional[Mapping[str, JSON]] = ...,
keyvault_credential: Optional[AsyncTokenCredential] = ...,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/appconfiguration/azure-appconfiguration-provider",
"Tag": "python/appconfiguration/azure-appconfiguration-provider_34a63910b7"
"Tag": "python/appconfiguration/azure-appconfiguration-provider_d3ca89ab22"
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from ._azureappconfigurationprovider import AzureAppConfigurationProvider
from ._models import (
AzureAppConfigurationKeyVaultOptions,
FeatureFlagSelector,
SettingSelector,
WatchKey,
)
Expand All @@ -18,6 +19,7 @@
"load",
"AzureAppConfigurationProvider",
"AzureAppConfigurationKeyVaultOptions",
"FeatureFlagSelector",
"SettingSelector",
"WatchKey",
]
Loading
Loading