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
An easy way to build your flask skeleton.

Flider What is Flider Flider is a lightweight framework that saves you time by creating a MVC compliant file structure and includes basic commonly use

Trevor Engen 8 Nov 17, 2022
Flask RESTful Web services using API to communicate between client and server.

Welcome! Open up two terminals, one for client and for server each Terminal 1 Terminal 2 Now navigate to the CW2_code directory in both like so $ cd C

Sehra Elahi 1 Nov 23, 2021
Criando um Bot com PYAUTOGUI e utilizando o Flask para Interface para Usuário

Criando um Bot com PYAUTOGUI e utilizando o Flask para Interface para Usuário O pyautogui foi escolhido pela possibilidade de fazer a identificação do

Rodrigo Vital 2 Oct 20, 2021
MongoEngine flask extension with WTF model forms support

Flask-MongoEngine Info: MongoEngine for Flask web applications. Repository: https://github.com/MongoEngine/flask-mongoengine About Flask-MongoEngine i

MongoEngine 815 Jan 03, 2023
This is a small notes web app, with python and flask microframework. Using sqlite3

Python Notes App. This is a small web application maked with flask-python for add notes easily and quickly. Dependencies. You can create a virtual env

Eduard 1 Dec 26, 2021
Force SSL on your Flask app.

Flask-SSLify This is a simple Flask extension that configures your Flask application to redirect all incoming requests to HTTPS. The extension is no l

Kenneth Reitz 26 Dec 07, 2022
Flask 文档中文翻译

Flask 中文文档 这里是 Flask 文档中文翻译项目,欢迎参与! 在开始翻译之前,请务必阅读下面的 Contributing Guide 了解贡献流程,然后阅读这个 Issue 了解翻译要求,在这个 Discussion 投票选出你认为合适的翻译词汇,在这个 Discussion 投票选出你喜

Grey Li 93 Nov 28, 2022
Basic flask system for login, api, and status system

Flask Multi Site With Login This is a basic website login system with an uncomplete api system NOTICE : This is NOT complete and is made to be a bare

MrShoe 0 Feb 02, 2022
Regex Converter for Flask URL Routes

Flask-Reggie Enable Regex Routes within Flask Installation pip install flask-reggie Configuration To enable regex routes within your application from

Rhys Elsmore 48 Mar 07, 2022
A YouTube webscraper made with flask.

YouTube Webscraper This website is for you to check all the stats on your favorite Youtube video! Technologies Python Flask HTML CSS Pafy Contributing

Proconsulates 3 Nov 25, 2021
Learn REST API with Flask, Mysql and Docker

Learn REST API with Flask, Mysql and Docker A project for you to learn to work a flask REST api with docker and the mysql database manager! Table of C

Aldo Matus 0 Jul 31, 2021
Flask Apps - Open-Source And Paid | AppSeed

Flask Apps Open-Source web apps built with automation tools, HTML parsing and boilerplated code in Flask - - Provided by AppSeed App Generator. What i

App Generator 120 Oct 04, 2022
flask extension for integration with the awesome pydantic package

Flask-Pydantic Flask extension for integration of the awesome pydantic package with Flask. Installation python3 -m pip install Flask-Pydantic Basics v

249 Jan 06, 2023
Small flask based opds catalog designed to serve a directory via OPDS

teenyopds Small flask based opds catalog designed to serve a directory via OPDS, it has currently only been verified to work with KyBook 3 on iOS but

Adam Furbee 4 Jul 14, 2022
This repo contains the Flask API to expose model and get predictions.

Tea Leaf Quality Srilanka Chapter This repo contains the Flask API to expose model and get predictions. Expose Model As An API Model Trainig will happ

DuKe786 2 Nov 12, 2021
REST API with mongoDB and Flask.

Flask REST API with mongoDB py 3.10 First, to install all dependencies: python -m pip install -r requirements.txt Second, into the ./src/ folder, cop

Luis Quiñones Requelme 3 Mar 05, 2022
A Microsub server built with Python Flask and SQLite.

Microsub Server This repository contains the code that powers my personal Microsub server. Microsub is an IndieWeb specification currently in developm

jamesg 8 Oct 26, 2022
É uma API feita em Python e Flask que pesquisa informações em uma tabela .xlsx e retorna o resultado.

API de rastreamento de pacotes É uma API feita em Python e Flask que pesquisa informações de rastreamento de pacotes em uma tabela .xlsx e retorna o r

Marcos Beraldo Barros 4 Jun 27, 2021
Map Matching & Weight Completion service - Java (Springboot) & Python(Flask)

Map Matching service to match coordinates to roads using Java and Springboot. Weight Completion service to fill in missing weights in a graph, using Python and Flask.

2 May 13, 2022
A Flask web application that manages student entries in a SQL database

Student Database App This is a Flask web application that manages student entries in a SQL database. Users can upload a CSV into the SQL database, mak

rebecca 1 Oct 20, 2021