Skip to content
Merged
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
133 changes: 100 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## Overview

Flaggle is a robust and flexible Python library for managing feature flags in your applications. With Flaggle, you can enable or disable features dynamically, perform gradual rollouts, and control feature availability without redeploying your code. Designed for simplicity and extensibility, Flaggle supports a variety of flag types and operations, making it easy to adapt to any project or workflow.
Flaggle is a robust and flexible Python library for managing feature flags in your applications. Feature flags (also known as feature toggles) are a software development technique that allows you to enable or disable features dynamically, perform gradual rollouts, and control feature availability without redeploying your code. Designed for simplicity and extensibility, Flaggle supports a variety of flag types and operations, making it easy to adapt to any project or workflow.

Whether you're building a small script or a large-scale production system, Flaggle helps you ship faster, experiment safely, and deliver value to your users with confidence.

Expand All @@ -15,8 +15,11 @@ Whether you're building a small script or a large-scale production system, Flagg
- [Overview](#overview)
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Getting Started](#getting-started)
- [Flaggle Class: Configuration & Usage](#flaggle-class-configuration--usage)
- [Supported Operations](#supported-operations)
- [Advanced Usage: The Flag Class](#advanced-usage-the-flag-class)
- [JSON Schema for Flags Endpoint](#json-schema-for-flags-endpoint)
- [Contributing](#contributing)
- [License](#license)
- [TODO / Roadmap](#todo--roadmap)
Expand Down Expand Up @@ -49,12 +52,12 @@ poetry add python-flaggle

---

## Usage
## Getting Started

### Basic Example
The easiest way to use Flaggle is to create a `Flaggle` instance that fetches feature flags from a remote JSON endpoint. This is the recommended and most common usage pattern.

```python
from flaggle import Flaggle
from python_flaggle import Flaggle

# Create a Flaggle instance that fetches flags from a remote endpoint
flaggle = Flaggle(url="https://api.example.com/flags", interval=60)
Expand All @@ -72,20 +75,50 @@ if flaggle.flags["env"].is_enabled("production"):
print("Production environment!")
```

### Manual Flag Creation (Advanced)
---

## Flaggle Class: Configuration & Usage

The `Flaggle` class is the main entry point for using feature flags in your application. It is designed to periodically fetch flag definitions from a remote JSON endpoint and provide a simple API for evaluating those flags at runtime.

You can also create flags manually if you want to bypass remote fetching:
### Initialization

```python
from flaggle import Flag, FlagOperation
from python_flaggle import Flaggle

flaggle = Flaggle(
url="https://api.example.com/flags", # Endpoint returning flag JSON
interval=60, # Polling interval in seconds (default: 60)
default_flags=None, # Optional: fallback flags if fetch fails
timeout=10, # HTTP timeout in seconds (default: 10)
verify_ssl=True # Verify SSL certificates (default: True)
)
```

flag = Flag(name="feature_x", value=True)
if flag.is_enabled():
print("Feature X is enabled!")
#### Parameters
| Parameter | Type | Description |
|-----------------|---------|------------------------------------------------------------------|
| `url` | str | The HTTP(S) endpoint to fetch the flags JSON from |
| `interval` | int | How often (in seconds) to poll for flag updates |
| `default_flags` | dict | (Optional) Fallback flags if remote fetch fails |
| `timeout` | int | (Optional) HTTP request timeout in seconds (default: 10) |
| `verify_ssl` | bool | (Optional) Whether to verify SSL certificates (default: True) |

flag = Flag(name="min_version", value=2, operation=FlagOperation.GE)
if flag.is_enabled(3):
print("Version is supported!")
#### Properties
- `flags`: A dictionary of flag name to `Flag` object, always up-to-date with the latest fetched values.
- `last_update`: The last time the flags were updated.
- `url`, `interval`, `timeout`, `verify_ssl`: The configuration values used.

#### Example Usage

```python
# Check if a feature is enabled
if flaggle.flags["feature_a"].is_enabled():
...

# Evaluate a flag with a custom value (e.g., for numeric or string flags)
if flaggle.flags["min_version"].is_enabled(5):
...
```

---
Expand All @@ -105,32 +138,31 @@ Flaggle supports a variety of operations for evaluating feature flags. These ope
| IN | Value is in a list/array | `FlagOperation.IN("BR", ["BR", "US"])` → `True` |
| NI | Value is not in a list/array | `FlagOperation.NI("FR", ["BR", "US"])` → `True` |

### Usage in Flag
---

## Advanced Usage: The Flag Class

For advanced scenarios, you can create and evaluate `Flag` objects directly, or load them from a JSON structure. This is useful for testing, custom flag sources, or when you want to bypass remote fetching.

You can specify an operation when creating a `Flag` to control how the flag is evaluated:
### Manual Flag Creation

```python
from flaggle import Flag, FlagOperation

# Numeric equality
flag = Flag(name="feature_x", value=42, operation=FlagOperation.EQ)
flag.is_enabled(42) # True
flag.is_enabled(10) # False

# String not equal
flag = Flag(name="env", value="prod", operation=FlagOperation.NE)
flag.is_enabled("dev") # True
flag.is_enabled("prod") # False

# Membership in array
flag = Flag(name="region", value=["US", "BR"], operation=FlagOperation.IN)
flag.is_enabled("US") # True
flag.is_enabled("FR") # False
from python_flaggle import Flag, FlagOperation

flag = Flag(name="feature_x", value=True)
if flag.is_enabled():
print("Feature X is enabled!")

flag = Flag(name="min_version", value=2, operation=FlagOperation.GE)
if flag.is_enabled(3):
print("Version is supported!")
```

You can also use the string representation of operations when loading flags from JSON:
### Loading Flags from JSON

```python
from python_flaggle import Flag

json_data = {
"flags": [
{"name": "feature_x", "value": 42, "operation": "eq"},
Expand All @@ -143,6 +175,41 @@ flags = Flag.from_json(json_data)

---

## JSON Schema for Flags Endpoint

The endpoint provided to `Flaggle` must return a JSON object with a top-level `flags` key, which is a list of flag definitions. Each flag definition should have the following structure:

```json
{
"flags": [
{
"name": "feature_a", // (string, required) Unique flag name
"description": "Enable feature A", // (string, optional) Human-readable description
"value": true, // (any, required) The flag value (bool, str, int, float, list, or null)
"operation": "eq" // (string, optional) Operation for evaluation (see below)
},
...
]
}
```

### Supported Operations
- `eq`, `ne`, `gt`, `ge`, `lt`, `le`, `in`, `ni`
- If `operation` is omitted, the flag is evaluated as a simple boolean/truthy value.

#### Example JSON
```json
{
"flags": [
{"name": "feature_a", "value": true},
{"name": "min_version", "value": 3, "operation": "ge"},
{"name": "region", "value": ["US", "BR"], "operation": "in"}
]
}
```

---

## Contributing

Contributions are welcome! Please open issues or submit pull requests for bug fixes, new features, or improvements. For major changes, please open an issue first to discuss what you would like to change.
Expand Down