diff --git a/README.md b/README.md index b35e20d..71bc5b6 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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) @@ -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) @@ -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): + ... ``` --- @@ -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"}, @@ -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.