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 funemployed, Previously Stripe, LinkedIn
Rachel Greenfield
A simple web application built using python flask. It can be used to scan SMEVai accounts for broken pages.

smescan A simple web application built using python flask. It can be used to scan SMEVai accounts for broken pages. Development Process Step 0: Clone

Abu Hurayra 1 Jan 30, 2022
Companion code to my O'Reilly book "Flask Web Development", second edition.

Flasky This repository contains the source code examples for the second edition of my O'Reilly book Flask Web Development. The commits and tags in thi

Miguel Grinberg 8k Dec 27, 2022
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
Full Stack Web Development with Flask.

Discover Flask Full Stack Web Development with Flask. http://discoverflask.com Flask is a micro web framework powered by Python. Its API is fairly sma

Real Python 4.4k Jan 06, 2023
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
Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development.

Flask-Starter Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development. It has all the r

Kundan Singh 259 Dec 26, 2022
Analytics snippets generator extension for the Flask framework.

Flask-Analytics Flask Analytics is an extension for Flask which generates analytics snippets for inclusion in templates. Installation $ pip install Fl

Mihir 80 Nov 30, 2022
OpenTracing instrumentation for the Flask microframework

Flask-OpenTracing This package enables distributed tracing in Flask applications via The OpenTracing Project. Once a production system contends with r

3rd-Party OpenTracing API Contributions 133 Dec 19, 2022
This is a simple web application using Python Flask and MySQL database.

Simple Web Application This is a simple web application using Python Flask and MySQL database. This is used in the demonstration of development of Ans

Alaaddin Tarhan 1 Nov 16, 2021
A web application that consists of a collection of board games

PyBoardGame About This website contains a collection of board games for users to enjoy, as well as various guides for the games. The web app is built

Larry Shi 0 Aug 11, 2021
Geometry Dash Song Bypass with Python Flask Server

Geometry Dash Song Bypass with Python Flask Server

pixelsuft‮ 1 Nov 16, 2021
Python3🐍 webApp to display your current playing music on OBS Studio.

Spotify Overlay A Overlay to display on Obs Studio or any related video/stream recorder, the current music that is playing on your Spotify. Installati

carlitos 0 Oct 17, 2022
docker-compose uWSGI nginx flask

docker-compose uWSGI nginx flask Note that this was tested on CentOS 7 Usage sudo yum install docker

Abdolkarim Saeedi 3 Sep 11, 2022
Flask Project Template A full feature Flask project template.

Flask Project Template A full feature Flask project template. See also Python-Project-Template for a lean, low dependency Python app. HOW TO USE THIS

Bruno Rocha 96 Dec 23, 2022
a flask profiler which watches endpoint calls and tries to make some analysis.

Flask-profiler version: 1.8 Flask-profiler measures endpoints defined in your flask application; and provides you fine-grained report through a web in

Mustafa Atik 718 Dec 20, 2022
Pf-flask-rest-com - Flask REST API Common Implementation by Problem Fighter Library

In the name of God, the Most Gracious, the Most Merciful. PF-Flask-Rest-Com Docu

Problem Fighter 3 Jan 15, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
Full text search for flask.

flask-msearch Installation To install flask-msearch: pip install flask-msearch # when MSEARCH_BACKEND = "whoosh" pip install whoosh blinker # when MSE

honmaple 197 Dec 29, 2022
Template for a rest app with flask, flask-rest and more...

Flask REST Template About the project (some comments): The ideia behind the project is to create an useful and simple template for an rest app . Besid

107 Nov 16, 2022
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