A Flask extension that enables or disables features based on configuration.

Overview

Flask FeatureFlags

PyPI version Build Status Coverage Status

This is a Flask extension that adds feature flagging to your applications. This lets you turn parts of your site on or off based on configuration.

It's useful for any setup where you deploy from trunk but want to hide unfinished features from your users, such as continuous integration builds.

You can also extend it to do simple a/b testing or whitelisting.

Installation

Installation is easy with pip:

pip install flask_featureflags

To install from source, download the source code, then run this:

python setup.py install

Flask-FeatureFlags supports Python 2.6, 2.7, and 3.3+ with experimental support for PyPy.

Version 0.1 of Flask-FeatureFlags supports Python 2.5 (but not Python 3), so use that version if you need it. Be aware that both Flask and Jinja have dropped support for Python 2.5.

Docs

For the most complete and up-to-date documentation, please see: https://flask-featureflags.readthedocs.org/en/latest/

Setup

Adding the extension is simple:

from flask import Flask
from flask_featureflags import FeatureFlag

app = Flask(__name__)

feature_flags = FeatureFlag(app)

In your Flask app.config, create a FEATURE_FLAGS dictionary, and add any features you want as keys. Any UTF-8 string is a valid feature name.

For example, to have 'unfinished_feature' hidden in production but active in development:

class ProductionConfig(Config):

    FEATURE_FLAGS = {
        'unfinished_feature' : False,
    }


class DevelopmentConfig(Config):

    FEATURE_FLAGS = {
      'unfinished_feature' : True,
    }

Note: If a feature flag is used in code but not defined in FEATURE_FLAGS, it's assumed to be off. Beware of typos.

If you want your app to throw an exception in dev when a feature flag is used in code but not defined, add this to your configuration:

RAISE_ERROR_ON_MISSING_FEATURES = True

If app.debug=True, this will throw a KeyError instead of silently ignoring the error.

Usage

Controllers/Views

If you want to protect an entire view:

from flask import Flask
import flask_featureflags as feature

@feature.is_active_feature('unfinished_feature', redirect_to='/old/url')
def index():
  # unfinished view code here

The redirect_to parameter is optional. If you don't specify, the url will return a 404.

If your needs are more complicated, you can check inside the view:

from flask import Flask
import flask_featureflags as feature

def index():
    if feature.is_active('unfinished_feature') and some_other_condition():
        # do new stuff
    else:
        # do old stuff

Templates

You can also check for features in Jinja template code:

{% if 'unfinished_feature' is active_feature %}
    new behavior here!
{% else %}
    old behavior...
{% endif %}

Using other backends

Want to store your flags somewhere other than the config file? There are third-party contrib modules for other backends.

Please see the documentation here: https://flask-featureflags.readthedocs.org/en/latest/contrib.html

Feel free to add your own - see CONTRIBUTING.rst for help.

Customization

If you need custom behavior, you can write your own feature flag handler.

A feature flag handler is simply a function that takes the feature name as input, and returns True (the feature is on) or False (the feature is off).

For example, if you want to enable features on Tuesdays:

from datetime import date

def is_it_tuesday(feature):
  return date.today().weekday() == 2:

You can register the handler like so:

from flask import Flask
from flask_featureflags import FeatureFlag

app = Flask(__name__)

feature_flags = FeatureFlag(app)
feature_flags.add_handler(is_it_tuesday)

If you want to remove a handler for any reason, simply do:

feature_flags.remove_handler(is_it_tuesday)

If you try to remove a handler that was never added, the code will silently ignore you.

To clear all handlers (thus effectively turning all features off):

feature_flags.clear_handlers()

Clearing handlers is also useful when you want to remove the built-in behavior of checking the FEATURE_FLAGS dictionary.

To enable all features on Tuesdays, no matter what the FEATURE_FLAGS setting says:

from flask import Flask
from flask_featureflags import FeatureFlag

app = Flask(__name__)

feature_flags = FeatureFlag(app)
feature_flags.clear_handlers()
feature_flags.add_handler(is_it_tuesday)

Chaining multiple handlers

You can define multiple handlers. If any of them return true, the feature is considered on.

For example, if you want features to be enabled on Tuesdays or Fridays:

feature_flags.add_handler(is_it_tuesday)
feature_flags.add_handler(is_it_friday)

Important: the order of handlers matters! The first handler to return True stops the chain. So given the above example, if it's Tuesday, is_it_tuesday will return True and is_it_friday will not run.

You can override this behavior by raising the StopCheckingFeatureFlags exception in your custom handler:

from flask_featureflags import StopCheckingFeatureFlags

def run_only_on_tuesdays(feature):
  if date.today().weekday() == 2:
    return True
  else:
    raise StopCheckingFeatureFlags

If it isn't Tuesday, this will cause the chain to return False and any other handlers won't run.

Acknowledgements

A big thank you to LinkedIn for letting me opensource this, and for my coworkers for all their feedback on this project. You guys are great. :)

Questions?

Feel free to ping me on twitter @trustrachel or on the Github project page.

Comments
  • add flask_featureflags.contrib sub package in install script

    add flask_featureflags.contrib sub package in install script

    This changeset fixes the installed packages. Previously, flask_featureflags.contrib sub packages (including inline and sqlalchemy) were not installed through pip install flask-featureflags.

    opened by iromli 6
  • Signal for missing keys

    Signal for missing keys

    I want to add the key to my sqlalchemy database if it does not exist in any other handler. I can listen to some flask signal in this case to do that.

    Is it a good idea? I can work on it, but maybe others have better ideas about how to handle it.

    opened by iurisilvio 5
  • Update __init__.py to fix ExtDeprecationWarning

    Update __init__.py to fix ExtDeprecationWarning

    This is the fix the following warning which happens whenever the module is loaded: ExtDeprecationWarning: Importing flask.ext.featureflags is deprecated, use flask_featureflags instead. from flask.ext.featureflags import NoFeatureFlagFound, log

    opened by Naishy 3
  • Add contrib modules to setup.py

    Add contrib modules to setup.py

    Was trying to use InlineFeatureFlag (as described here), but found that the contrib modules weren't being included. Small change to setup.py fixes it.

    opened by pcraig3 3
  • SQLAlchemy handler

    SQLAlchemy handler

    My proposal to make an SQLAlchemy handler.

    You just need a SQLAlchemy instance (from Flask-SQLAlchemy extension) and a check method in the model.

    from flask import Flask
    from flask.ext.sqlalchemy import SQLAlchemy
    from flask.ext.featureflags import FeatureFlag
    from flask.ext.featureflags.contrib.sqlalchemy import SQLAlchemyFeatureFlags
    
    app = Flask(__name__)
    db = SQLAlchemy(app)
    handler = SQLAlchemyFeatureFlags(db)
    
    ff = FeatureFlag(app)
    ff.add_handlers(handler)
    
    opened by iurisilvio 3
  • Feature flag application backend

    Feature flag application backend

    As a fellow lover of python and flask, and having written a feature-switching backend application with an administrative UI, I would like to contribute an integration between the two. Is that something you'd be interested in?

    https://github.com/giftig/flippy

    I was actually inspired by gargoyle / django-gargoule when writing flippy, which worked very similarly to your lib.

    I'm genuinely not sure why I've never written my own python connector to it.

    opened by giftig 2
  • consistent version in __init__.py and setup.py

    consistent version in __init__.py and setup.py

    Previously, flask_featureflags.__version__ is set to 0.4dev while setup.py is set to 0.7-dev. This changeset ensures consistent version found in flask_featureflags.__version__ and setup.py.

    You can check the version in Python shell:

    >>> import flask_featureflags
    >>> print(flask_featureflags.__version__)
    0.7-dev
    

    and using pip freeze:

    $ pip freeze | grep FeatureFlags
    Flask-FeatureFlags==0.7.dev0
    
    opened by iromli 2
  • Add custom handler to add inline feature flags

    Add custom handler to add inline feature flags

    The changesets introduce custom handler for inline feature flags.

    One notable difference is, instead of specifying feature flags in dict-style:

    FEATURE_FLAGS = {
        "finished": False,
    }
    

    the flag must be written in uppercased plain string with FEATURE_FLAGS_X where X is the feature name:

    FEATURE_FLAGS_FINISHED = False
    

    The motivation behind this custom handler is to interopt with other Flask extensions, e.g. Flask-AppConfig.

    opened by iromli 2
  • Adding route definition to example

    Adding route definition to example

    This tripped me up a bit, so thought explicitly stating the order of decorators could help.

    This works (404s):

    @app.route('/feature-flag-test-route')
    @is_active_feature('test_route')
    def feature_flag_test_route():
        return 'on!'
    

    This does not (returns 200, displays 'on!')

    @is_active_feature('test_route')
    @app.route('/feature-flag-test-route')
    def feature_flag_test_route():
        return 'on!'
    
    opened by jskulski 1
  • Raise NoFeatureFlagFound instead of handle missing flags

    Raise NoFeatureFlagFound instead of handle missing flags

    The handler is not responsible to handle the feature flag missing. I expect the KeyError only if it was not found in any handler.

    The current implementation works for only one handler.

    This is my first step to create a custom handler. I want to make the core responsible for missing keys.

    I'm not sure about the exception name. Django use DoesNotExist, SQLAlchemy use NoResultFound, but I tried FeatureFlagNotFound, NotFound, FeatureNotFound and others.

    opened by iurisilvio 1
  • Add argument redirect (optional) to is_active_feature

    Add argument redirect (optional) to is_active_feature

    It's not possible to use url_for() in the decorator call if the app context is not build yet. Therefore this patch adds a new optional argument named redirect to is_active_feature. It's the same as redirect_to but it triggers url_for() right before the redirect.

    opened by michaelcontento 1
  • Fix imports to remove warning per Flask recommendation.

    Fix imports to remove warning per Flask recommendation.

    Flask no longer recommend using the "flask.ext." import style; this change eliminates the warning currently generated by flask when using this extension.

    http://flask.pocoo.org/docs/0.12/extensiondev/#extension-import-transition

    (The 0.12 docs are somewhat contradictory on this, but the confusing text seems to have been removed in the latest dev docs.)

    opened by galund 1
Releases(0.6)
  • 0.6(Jun 10, 2015)

  • 0.5.1(Oct 13, 2014)

    Adding the ability to have feature flags inline instead of in a dictionary, to make it easier to interoperate with other Flask extensions, e.g. Flask-AppConfig.

    A big thank you to Isman Firmansyah (@iromli) for the contribution!

    Source code(tar.gz)
    Source code(zip)
  • 0.5(Aug 7, 2014)

    Official support for contributed modules, thank you to iurisilvio! He contributed the first for SQLAlchemy, so you can store your flags in the database instead.

    Contributions for other storage backends welcome!

    Source code(tar.gz)
    Source code(zip)
  • 0.4(Apr 8, 2014)

    • General code cleanup, modernization and optimization
    • Adding optional redirect to is_active_feature, thank you to michaelcontento
    • Fixed syntax error in docs, thank you to iurisilvio
    Source code(tar.gz)
    Source code(zip)
Owner
Rachel Greenfield
Currently funlancing, Previously Stripe, LinkedIn
Rachel Greenfield
A rate limiter for Starlette and FastAPI

SlowApi A rate limiting library for Starlette and FastAPI adapted from flask-limiter. Note: this is alpha quality code still, the API may change, and

Laurent Savaete 562 Jan 01, 2023
🚀 Cookiecutter Template for FastAPI + React Projects. Using PostgreSQL, SQLAlchemy, and Docker

FastAPI + React · A cookiecutter template for bootstrapping a FastAPI and React project using a modern stack. Features FastAPI (Python 3.8) JWT authen

Gabriel Abud 1.4k Jan 02, 2023
Turns your Python functions into microservices with web API, interactive GUI, and more.

Instantly turn your Python functions into production-ready microservices. Deploy and access your services via HTTP API or interactive UI. Seamlessly export your services into portable, shareable, and

Machine Learning Tooling 2.8k Jan 04, 2023
Twitter API monitor with fastAPI + MongoDB

Twitter API monitor with fastAPI + MongoDB You need to have a file .env with the following variables: DB_URL="mongodb+srv://mongodb_path" DB_URL2=

Leonardo Ferreira 3 Apr 08, 2022
Farlimit - FastAPI rate limit with python

FastAPIRateLimit Contributing is F&E (free&easy) Y Usage pip install farlimit N

omid 27 Oct 06, 2022
FastAPI CRUD template using Deta Base

Deta Base FastAPI CRUD FastAPI CRUD template using Deta Base Setup Install the requirements for the CRUD: pip3 install -r requirements.txt Add your D

Sebastian Ponce 2 Dec 15, 2021
This project shows how to serve an ONNX-optimized image classification model as a web service with FastAPI, Docker, and Kubernetes.

Deploying ML models with FastAPI, Docker, and Kubernetes By: Sayak Paul and Chansung Park This project shows how to serve an ONNX-optimized image clas

Sayak Paul 104 Dec 23, 2022
京东图片点击验证码识别

京东图片验证码识别 本项目是@yqchilde 大佬的 JDMemberCloseAccount 识别图形验证码(#45)思路验证,若你也有思路可以提交Issue和PR也可以在 @yqchilde 的 TG群 找到我 声明 本脚本只是为了学习研究使用 本脚本除了采集处理验证码图片没有其他任何功能,也

AntonVanke 37 Dec 22, 2022
cookiecutter template for web API with python

Python project template for Web API with cookiecutter What's this This provides the project template including minimum test/lint/typechecking package

Hitoshi Manabe 4 Jan 28, 2021
API using python and Fastapi framework

Welcome 👋 CFCApi is a API DEVELOPMENT PROJECT UNDER CODE FOR COMMUNITY ! Project Walkthrough 🚀 CFCApi run on Python using FASTapi Framework Docs The

Abhishek kushwaha 7 Jan 02, 2023
Minecraft biome tile server writing on Python using FastAPI

Blocktile Minecraft biome tile server writing on Python using FastAPI Usage https://blocktile.herokuapp.com/overworld/{seed}/{zoom}/{col}/{row}.png s

Vladimir 2 Aug 31, 2022
implementation of deta base for FastAPIUsers

FastAPI Users - Database adapter for Deta Base Ready-to-use and customizable users management for FastAPI Documentation: https://fastapi-users.github.

2 Aug 15, 2022
fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability

FastAPI2 Admin Introduction fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability. Now

Glib 14 Dec 05, 2022
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 310 Dec 14, 2022
🐞 A debug toolbar for FastAPI based on the original django-debug-toolbar. 🐞

Debug Toolbar 🐞 A debug toolbar for FastAPI based on the original django-debug-toolbar. 🐞 Swagger UI & GraphQL are supported. Documentation: https:/

Dani 74 Dec 30, 2022
Browse JSON API in a HTML interface.

Falcon API Browse This project provides a middleware for Falcon Web Framework that will render the response in an HTML form for documentation purpose.

Abhilash Raj 4 Mar 16, 2022
Opinionated authorization package for FastAPI

FastAPI Authorization Installation pip install fastapi-authorization Usage Currently, there are two models available: RBAC: Role-based Access Control

Marcelo Trylesinski 18 Jul 04, 2022
api versioning for fastapi web applications

fastapi-versioning api versioning for fastapi web applications Installation pip install fastapi-versioning Examples from fastapi import FastAPI from f

Dean Way 472 Jan 02, 2023
🚢 Docker images and utilities to power your Python APIs and help you ship faster. With support for Uvicorn, Gunicorn, Starlette, and FastAPI.

🚢 inboard 🐳 Docker images and utilities to power your Python APIs and help you ship faster. Description This repository provides Docker images and a

Brendon Smith 112 Dec 30, 2022
Sample project showing reliable data ingestion application using FastAPI and dramatiq

Create and deploy a reliable data ingestion service with FastAPI, SQLModel and Dramatiq This is the source code for the data ingestion service explain

François Voron 31 Nov 30, 2022