Python SDK for FOFF Feature Config service
Project description
FOFF Python SDK
This document covers how to integrate with the FOFF Feature Config Service using the Python SDK.
Installation
Please head over to foff.twospoon.ai and create your first feature config. Then integrate it in your codebase using the following steps.
Dependency Installation
Install the dependency using the following command:
pip install foff
Requires Python 3.10 or later.
Quick Start
Sync Client
Proceed to create the client:
from foff import Client, Config
# STEP 1: Create appropriate config
config = Config(
api_key="your-api-key",
base_url="https://foff.twospoon.ai/live",
scope="name-of-your-scope",
polling_interval=30, # refresh configs every 30 seconds (0 to disable)
)
# STEP 2: Create the client with the config
with Client(config) as client:
# STEP 3: Retrieve configs for your created features for given hierarchies
value = client.get_feature_config("my-feature", ["org-1", "team-a", "user-123"])
print(value)
Async Client
import asyncio
from foff import AsyncClient, Config
config = Config(
api_key="your-api-key",
base_url="https://foff.twospoon.ai/live",
scope="name-of-your-scope",
polling_interval=30,
)
async def main():
async with AsyncClient(config) as client:
value = client.get_feature_config("my-feature", ["org-1", "team-a", "user-123"])
print(value)
asyncio.run(main())
Configuration
The SDK is configured via the foff.Config dataclass:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
api_key |
str |
Yes | Your FOFF API key. | |
base_url |
str |
Yes | Base URL of the FOFF API. | |
scope |
str |
Yes | The scope to fetch configs for, such as production or staging. |
|
polling_interval |
int |
No | 30 |
How often, in seconds, to poll for config updates. Use 0 to disable polling. |
Validation
Creating a Client or AsyncClient validates the config and raises ValueError if api_key, base_url, or scope is empty.
Creating a Client
Sync Client
with Client(config) as client:
value = client.get_feature_config("dark-mode", ["org-1", "team-a", "user-123"])
Async Client
async with AsyncClient(config) as client:
value = client.get_feature_config("dark-mode", ["org-1", "team-a", "user-123"])
Fetching Feature Configs
get_feature_config(feature_name: str, ordered_hierarchy: list[str]) -> Any
Returns the config value for a feature, resolved against a hierarchy. The provided hierarchy must have the same number of levels as the scope's configured hierarchy.
value = client.get_feature_config("dark-mode", ["org-1", "team-a", "user-123"])
Hierarchy resolution works from most specific to least specific:
- The SDK looks up the most specific combination first.
- For the example above, it checks keys in this order:
org-1 + team-a + user-123org-1 + team-aorg-1
- If none match, it falls back to the
"default"value of the config for a feature. - If the feature does not exist at all, it returns
None.
This lets you define config overrides at any level of your hierarchy, such as organisation -> team -> user or environment -> region -> service, and the SDK resolves the most specific value automatically.
Polling
When polling_interval > 0, the client refreshes configs in the background.
- Polling errors are silently ignored, and the SDK continues serving the last successfully fetched config.
- Calling
close()onClient, orawait close()onAsyncClient, stops background polling and releases resources.
Recommended Intervals
| Use Case | Interval |
|---|---|
| Near-real-time | 10s |
| Standard | 30-60s |
| Low-traffic / batch | 300-600s |
Client Lifecycle
Sync
# Context manager (recommended)
with Client(config) as client:
...
# Manual
client = Client(config)
try:
...
finally:
client.close()
Async
# Context manager (recommended)
async with AsyncClient(config) as client:
...
# Manual
client = AsyncClient(config)
await client.start()
try:
...
finally:
await client.close()
Contributing
Issues and pull requests are tracked on GitHub.
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file foff-0.2.0.tar.gz.
File metadata
- Download URL: foff-0.2.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a132d83808b8805c28d5d9bd6ba769f066f0a10c52d5c86e97cc44ea69fc557b
|
|
| MD5 |
84d3d645724198835afe9d30035ae518
|
|
| BLAKE2b-256 |
a7870aecb8f1e5b65a858a66bbce0a7383544dc450dbde88d60742dafc84e250
|
Provenance
The following attestation bundles were made for foff-0.2.0.tar.gz:
Publisher:
release.yml on twospoon/foff-feature-config-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foff-0.2.0.tar.gz -
Subject digest:
a132d83808b8805c28d5d9bd6ba769f066f0a10c52d5c86e97cc44ea69fc557b - Sigstore transparency entry: 1341811933
- Sigstore integration time:
-
Permalink:
twospoon/foff-feature-config-python-sdk@945ca9c3dead3ce3d10b879067d91bcb77687057 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/twospoon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@945ca9c3dead3ce3d10b879067d91bcb77687057 -
Trigger Event:
release
-
Statement type:
File details
Details for the file foff-0.2.0-py3-none-any.whl.
File metadata
- Download URL: foff-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0afdffc0214ceefbea2cba7f6125989b054ff0b22928c941679ab619764ee55c
|
|
| MD5 |
fb61195c6a5aadafd184bb628f86d794
|
|
| BLAKE2b-256 |
2dd5d33bd1defc96b7f7aeb5209683baf34dde8d9fcf2e53118deb12d98e37ee
|
Provenance
The following attestation bundles were made for foff-0.2.0-py3-none-any.whl:
Publisher:
release.yml on twospoon/foff-feature-config-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foff-0.2.0-py3-none-any.whl -
Subject digest:
0afdffc0214ceefbea2cba7f6125989b054ff0b22928c941679ab619764ee55c - Sigstore transparency entry: 1341811943
- Sigstore integration time:
-
Permalink:
twospoon/foff-feature-config-python-sdk@945ca9c3dead3ce3d10b879067d91bcb77687057 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/twospoon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@945ca9c3dead3ce3d10b879067d91bcb77687057 -
Trigger Event:
release
-
Statement type: