Metadata-Version: 1.1
Name: Flask-Injector
Version: 0.3.3
Summary: Adds Injector, a Dependency Injection framework, support to Flask.
Home-page: https://github.com/alecthomas/flask_injector
Author: Alec Thomas
Author-email: alec@swapoff.org
License: BSD
Description: Flask-Injector
        ==============
        
        .. image:: https://secure.travis-ci.org/alecthomas/flask_injector.png?branch=master
           :alt: Build status
           :target: https://travis-ci.org/alecthomas/flask_injector
        
        
        Adds `Injector <https://github.com/alecthomas/injector>`_ support to Flask,
        this way there's no need to use global Flask objects, which makes testing simpler.
        
        Injector is a dependency-injection framework for Python, inspired by Guice.
        
        `Flask-Injector` is compatible with CPython 2.6-2.7, 3.3+ and PyPy 1.9+. As of version
        0.3.0 it requires Injector version 0.7.4 or greater.
        
        
        Example application using flask_injector
        ----------------------------------------
        
        Create your Flask application:
        
        .. code:: python
        
            import sqlite3
            from flask import Flask, Config
            from flask.views import View
            from flask_injector import init_app, post_init_app
            from injector import Injector, inject
        
            app = Flask(__name__)
        
        Update the `Flask` app configuration as normal, additionally passing in any
        configuration for modules:
        
        .. code:: python
        
            app.config.update(
                DB_CONNECTION_STRING=':memory:',
            )
        
        In the Injector world, all dependency configuration and initialization is
        performed in `modules <http://packages.python.org/injector/#module>`_. The
        same is true with Flask-Injector. You can see some examples of configuring
        Flask extensions through modules below.
        
        Accordingly, the next step is to create modules for any objects we want made
        available to the application. Note that in this example we also use the
        injector to gain access to the `flask.Config`:
        
        .. code:: python
        
            # Configure our SQLite connection object
            @inject(config=Config)
            def configure(binder, config):
                binder.bind(
                    sqlite3.Connection,
                    to=sqlite3.Connection(config['DB_CONNECTION_STRING']),
                    scope=request,
                )
        
        Now perform Injector Flask application integration initialization. This needs to
        be run before any views, handlers, etc. are configured for the application:
        
        .. code:: python
        
            injector = init_app(app=app, modules=[configure])
        
        You can also provide already existing Injector instance:
        
        .. code:: python
        
           injector = your_initialization_code()
           # ...
           init_app(app=app, injector=injector)
        
        Configure your application by attaching views, handlers, context processors etc.:
        
        .. code:: python
        
            # Putting all views configuration in a function is an example of how can
            # you stop depending on global app object
            def configure_views(app):
                @app.route("/bar")
                def bar():
                    return render("bar.html")
        
        
                # Route with injection
                @app.route("/foo")
                @inject(db=sqlite3.Connection)
                def foo(db):
                    users = db.execute('SELECT * FROM users').all()
                    return render("foo.html")
        
        
                # Class-based view with injected constructor
                class Waz(View):
                    @inject(db=sqlite3.Connection)
                    def __init__(self, db):
                        self.db = db
        
                    def dispatch_request(self, key):
                        users = self.db.execute('SELECT * FROM users WHERE name=?', (key,)).all()
                        return 'waz'
        
                app.add_url_rule('/waz/<key>', view_func=Waz.as_view('waz'))
        
            configure_views(app)
        
        Run the post-initialization step. This needs to be run only after you attached all
        views, handlers etc.:
        
        .. code:: python
        
            post_init_app(app=app, injector=injector)
        
        Run the Flask application as normal:
        
        .. code:: python
        
            app.run()
        
        See `example.py` for a more complete example, including `Flask-SQLAlchemy` and
        `Flask-Cache` integration.
        
        Supporting Flask Extensions
        ---------------------------
        
        Typically, Flask extensions are initialized at the global scope using a
        pattern similar to the following.
        
        .. code:: python
        
            app = Flask(__name__)
            ext = ExtClass(app)
        
            @app.route(...)
            def view():
                # Use ext object here...
        
        As we don't have these globals with Flask-Injector we have to configure the
        extension the Injector way - through modules. Modules can either be subclasses
        of `injector.Module` or a callable taking an `injector.Binder` instance.
        
        .. code:: python
        
            @inject(app=Flask)
            def configure_ext(binder, app):
                binder.bind(ExtClass, to=ExtClass(app), scope=singleton)
        
            def main():
                app = Flask(__name__)
                app.config.update(
                    EXT_CONFIG_VAR='some_value',
                )
        
                injector = init_app(app=app, modules=[configure_ext])
                # attach your views etc. here
                post_init_app(app=app, injector=injector)
        
                app.run()
        
        *Make sure to bind extension objects as singletons.*
        
        Working Example 1: Flask-SQLAlchemy integration
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        
        This is a full working example of integrating Flask-SQLAlchemy.
        
        We use standard SQLAlchemy models rather than the Flask-SQLAlchemy magic.
        
        .. code:: python
        
            from sqlalchemy.ext.declarative import declarative_base
            from sqlalchemy import Column, String
        
            Base = declarative_base()
        
        
            class KeyValue(Base):
                __tablename__ = 'data'
        
                key = Column(String, primary_key=True)
                value = Column(String)
        
                def __init__(self, key, value):
                    self.key = key
                    self.value = value
        
        And to register the Flask-SQLAlchemy extension.
        
        .. code:: python
        
            from flast.ext.sqlalchemy import SQLAlchemy
        
            @inject(app=Flask)
            class FlaskSQLAlchemyModule(Module):
                def configure(self, binder):
                    db = self.configure_db(self.app)
                    binder.bind(SQLAlchemy, to=db, scope=singleton)
        
                def configure_db(self, app):
                    db = SQLAlchemy(app)
                    Base.metadata.create_all(db.engine)
                    db.session.add_all([
                        KeyValue('hello', 'world'),
                        KeyValue('goodbye', 'cruel world'),
                    ])
                    db.session.commit()
                    return db
        
        Working Example 2: Flask-Cache integration
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        
        .. code:: python
        
            @inject(app=Flask)
            class CacheModule(Module):
                """Configure the application."""
                def configure(self, binder):
                    binder.bind(Cache, to=Cache(self.app), scope=singleton)
        
Keywords: Dependency Injection,Flask
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Utilities
Classifier: Framework :: Flask
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
