Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/studio/static/doc/flask-docs/extensiondev.html
diff options
context:
space:
mode:
Diffstat (limited to 'studio/static/doc/flask-docs/extensiondev.html')
-rw-r--r--studio/static/doc/flask-docs/extensiondev.html475
1 files changed, 475 insertions, 0 deletions
diff --git a/studio/static/doc/flask-docs/extensiondev.html b/studio/static/doc/flask-docs/extensiondev.html
new file mode 100644
index 0000000..05044b0
--- /dev/null
+++ b/studio/static/doc/flask-docs/extensiondev.html
@@ -0,0 +1,475 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <title>Flask Extension Development &mdash; Flask 0.8 documentation</title>
+
+ <link rel="stylesheet" href="_static/flasky.css" type="text/css" />
+ <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '',
+ VERSION: '0.8',
+ COLLAPSE_INDEX: false,
+ FILE_SUFFIX: '.html',
+ HAS_SOURCE: true
+ };
+ </script>
+ <script type="text/javascript" src="_static/jquery.js"></script>
+ <script type="text/javascript" src="_static/underscore.js"></script>
+ <script type="text/javascript" src="_static/doctools.js"></script>
+ <link rel="top" title="Flask 0.8 documentation" href="index.html" />
+ <link rel="next" title="Pocoo Styleguide" href="styleguide.html" />
+ <link rel="prev" title="Unicode in Flask" href="unicode.html" />
+
+
+ <link rel="apple-touch-icon" href="_static/touch-icon.png" />
+
+ <link media="only screen and (max-device-width: 480px)" href="_static/small_flask.css" type= "text/css" rel="stylesheet" />
+
+ </head>
+ <body>
+ <div class="related">
+ <h3>Navigation</h3>
+ <ul>
+ <li class="right" style="margin-right: 10px">
+ <a href="genindex.html" title="General Index"
+ accesskey="I">index</a></li>
+ <li class="right" >
+ <a href="styleguide.html" title="Pocoo Styleguide"
+ accesskey="N">next</a> |</li>
+ <li class="right" >
+ <a href="unicode.html" title="Unicode in Flask"
+ accesskey="P">previous</a> |</li>
+ <li><a href="index.html">Flask 0.8 documentation</a> &raquo;</li>
+ </ul>
+ </div>
+
+ <div class="document">
+ <div class="documentwrapper">
+ <div class="bodywrapper">
+ <div class="body">
+
+ <div class="section" id="flask-extension-development">
+<h1>Flask Extension Development<a class="headerlink" href="#flask-extension-development" title="Permalink to this headline">¶</a></h1>
+<p>Flask, being a microframework, often requires some repetitive steps to get
+a third party library working. Because very often these steps could be
+abstracted to support multiple projects the <a class="reference external" href="http://flask.pocoo.org/extensions/">Flask Extension Registry</a>
+was created.</p>
+<p>If you want to create your own Flask extension for something that does not
+exist yet, this guide to extension development will help you get your
+extension running in no time and to feel like users would expect your
+extension to behave.</p>
+<div class="section" id="anatomy-of-an-extension">
+<h2>Anatomy of an Extension<a class="headerlink" href="#anatomy-of-an-extension" title="Permalink to this headline">¶</a></h2>
+<p>Extensions are all located in a package called <tt class="docutils literal"><span class="pre">flask_something</span></tt>
+where &#8220;something&#8221; is the name of the library you want to bridge. So for
+example if you plan to add support for a library named <cite>simplexml</cite> to
+Flask, you would name your extension&#8217;s package <tt class="docutils literal"><span class="pre">flask_simplexml</span></tt>.</p>
+<p>The name of the actual extension (the human readable name) however would
+be something like &#8220;Flask-SimpleXML&#8221;. Make sure to include the name
+&#8220;Flask&#8221; somewhere in that name and that you check the capitalization.
+This is how users can then register dependencies to your extension in
+their <cite>setup.py</cite> files.</p>
+<p>Flask sets up a redirect package called <tt class="xref py py-data docutils literal"><span class="pre">flask.ext</span></tt> where users
+should import the extensions from. If you for instance have a package
+called <tt class="docutils literal"><span class="pre">flask_something</span></tt> users would import it as
+<tt class="docutils literal"><span class="pre">flask.ext.something</span></tt>. This is done to transition from the old
+namespace packages. See <a class="reference internal" href="#ext-import-transition"><em>Extension Import Transition</em></a> for more details.</p>
+<p>But how do extensions look like themselves? An extension has to ensure
+that it works with multiple Flask application instances at once. This is
+a requirement because many people will use patterns like the
+<a class="reference internal" href="patterns/appfactories.html#app-factories"><em>Application Factories</em></a> pattern to create their application as needed to aid
+unittests and to support multiple configurations. Because of that it is
+crucial that your application supports that kind of behaviour.</p>
+<p>Most importantly the extension must be shipped with a <cite>setup.py</cite> file and
+registered on PyPI. Also the development checkout link should work so
+that people can easily install the development version into their
+virtualenv without having to download the library by hand.</p>
+<p>Flask extensions must be licensed as BSD or MIT or a more liberal license
+to be enlisted on the Flask Extension Registry. Keep in mind that the
+Flask Extension Registry is a moderated place and libraries will be
+reviewed upfront if they behave as required.</p>
+</div>
+<div class="section" id="hello-flaskext">
+<h2>&#8220;Hello Flaskext!&#8221;<a class="headerlink" href="#hello-flaskext" title="Permalink to this headline">¶</a></h2>
+<p>So let&#8217;s get started with creating such a Flask extension. The extension
+we want to create here will provide very basic support for SQLite3.</p>
+<p>First we create the following folder structure:</p>
+<div class="highlight-python"><pre>flask-sqlite3/
+ flask_sqlite3.py
+ LICENSE
+ README</pre>
+</div>
+<p>Here&#8217;s the contents of the most important files:</p>
+<div class="section" id="setup-py">
+<h3>setup.py<a class="headerlink" href="#setup-py" title="Permalink to this headline">¶</a></h3>
+<p>The next file that is absolutely required is the <cite>setup.py</cite> file which is
+used to install your Flask extension. The following contents are
+something you can work with:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">Flask-SQLite3</span>
+<span class="sd">-------------</span>
+
+<span class="sd">This is the description for that library</span>
+<span class="sd">&quot;&quot;&quot;</span>
+<span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
+
+
+<span class="n">setup</span><span class="p">(</span>
+ <span class="n">name</span><span class="o">=</span><span class="s">&#39;Flask-SQLite3&#39;</span><span class="p">,</span>
+ <span class="n">version</span><span class="o">=</span><span class="s">&#39;1.0&#39;</span><span class="p">,</span>
+ <span class="n">url</span><span class="o">=</span><span class="s">&#39;http://example.com/flask-sqlite3/&#39;</span><span class="p">,</span>
+ <span class="n">license</span><span class="o">=</span><span class="s">&#39;BSD&#39;</span><span class="p">,</span>
+ <span class="n">author</span><span class="o">=</span><span class="s">&#39;Your Name&#39;</span><span class="p">,</span>
+ <span class="n">author_email</span><span class="o">=</span><span class="s">&#39;your-email@example.com&#39;</span><span class="p">,</span>
+ <span class="n">description</span><span class="o">=</span><span class="s">&#39;Very short description&#39;</span><span class="p">,</span>
+ <span class="n">long_description</span><span class="o">=</span><span class="n">__doc__</span><span class="p">,</span>
+ <span class="n">py_modules</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;flask_sqlite3&#39;</span><span class="p">],</span>
+ <span class="c"># if you would be using a package instead use packages instead</span>
+ <span class="c"># of py_modules:</span>
+ <span class="c"># packages=[&#39;flask_sqlite3&#39;],</span>
+ <span class="n">zip_safe</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
+ <span class="n">include_package_data</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
+ <span class="n">platforms</span><span class="o">=</span><span class="s">&#39;any&#39;</span><span class="p">,</span>
+ <span class="n">install_requires</span><span class="o">=</span><span class="p">[</span>
+ <span class="s">&#39;Flask&#39;</span>
+ <span class="p">],</span>
+ <span class="n">classifiers</span><span class="o">=</span><span class="p">[</span>
+ <span class="s">&#39;Environment :: Web Environment&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Intended Audience :: Developers&#39;</span><span class="p">,</span>
+ <span class="s">&#39;License :: OSI Approved :: BSD License&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Operating System :: OS Independent&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Programming Language :: Python&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Topic :: Internet :: WWW/HTTP :: Dynamic Content&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Topic :: Software Development :: Libraries :: Python Modules&#39;</span>
+ <span class="p">]</span>
+<span class="p">)</span>
+</pre></div>
+</div>
+<p>That&#8217;s a lot of code but you can really just copy/paste that from existing
+extensions and adapt.</p>
+</div>
+<div class="section" id="flask-sqlite3-py">
+<h3>flask_sqlite3.py<a class="headerlink" href="#flask-sqlite3-py" title="Permalink to this headline">¶</a></h3>
+<p>Now this is where your extension code goes. But how exactly should such
+an extension look like? What are the best practices? Continue reading
+for some insight.</p>
+</div>
+</div>
+<div class="section" id="initializing-extensions">
+<h2>Initializing Extensions<a class="headerlink" href="#initializing-extensions" title="Permalink to this headline">¶</a></h2>
+<p>Many extensions will need some kind of initialization step. For example,
+consider your application is currently connecting to SQLite like the
+documentation suggests (<a class="reference internal" href="patterns/sqlite3.html#sqlite3"><em>Using SQLite 3 with Flask</em></a>) you will need to provide a few
+functions and before / after request handlers. So how does the extension
+know the name of the application object?</p>
+<p>Quite simple: you pass it to it.</p>
+<p>There are two recommended ways for an extension to initialize:</p>
+<dl class="docutils">
+<dt>initialization functions:</dt>
+<dd>If your extension is called <cite>helloworld</cite> you might have a function
+called <tt class="docutils literal"><span class="pre">init_helloworld(app[,</span> <span class="pre">extra_args])</span></tt> that initializes the
+extension for that application. It could attach before / after
+handlers etc.</dd>
+<dt>classes:</dt>
+<dd>Classes work mostly like initialization functions but can later be
+used to further change the behaviour. For an example look at how the
+<a class="reference external" href="http://packages.python.org/Flask-OAuth/">OAuth extension</a> works: there is an <cite>OAuth</cite> object that provides
+some helper functions like <cite>OAuth.remote_app</cite> to create a reference to
+a remote application that uses OAuth.</dd>
+</dl>
+<p>What to use depends on what you have in mind. For the SQLite 3 extension
+we will use the class based approach because it will provide users with a
+manager object that handles opening and closing database connections.</p>
+</div>
+<div class="section" id="the-extension-code">
+<h2>The Extension Code<a class="headerlink" href="#the-extension-code" title="Permalink to this headline">¶</a></h2>
+<p>Here&#8217;s the contents of the <cite>flask_sqlite3.py</cite> for copy/paste:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">absolute_import</span>
+<span class="kn">import</span> <span class="nn">sqlite3</span>
+
+<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">_request_ctx_stack</span>
+
+<span class="k">class</span> <span class="nc">SQLite3</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;SQLITE3_DATABASE&#39;</span><span class="p">,</span> <span class="s">&#39;:memory:&#39;</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">teardown_request</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">teardown_request</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">before_request</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">before_request</span><span class="p">)</span>
+
+ <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="k">return</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s">&#39;SQLITE3_DATABASE&#39;</span><span class="p">])</span>
+
+ <span class="k">def</span> <span class="nf">before_request</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">teardown_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">get_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="k">if</span> <span class="n">ctx</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
+ <span class="k">return</span> <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span>
+</pre></div>
+</div>
+<p>So here&#8217;s what these lines of code do:</p>
+<ol class="arabic simple">
+<li>The <tt class="docutils literal"><span class="pre">__future__</span></tt> import is necessary to activate absolute imports.
+Otherwise we could not call our module <cite>sqlite3.py</cite> and import the
+top-level <cite>sqlite3</cite> module which actually implements the connection to
+SQLite.</li>
+<li>We create a class for our extension that requires a supplied <cite>app</cite> object,
+sets a configuration for the database if it&#8217;s not there
+(<a class="reference external" href="http://docs.python.org/dev/library/stdtypes.html#dict.setdefault" title="(in Python v3.3)"><tt class="xref py py-meth docutils literal"><span class="pre">dict.setdefault()</span></tt></a>), and attaches <cite>before_request</cite> and
+<cite>teardown_request</cite> handlers.</li>
+<li>Next, we define a <cite>connect</cite> function that opens a database connection.</li>
+<li>Then we set up the request handlers we bound to the app above. Note here
+that we&#8217;re attaching our database connection to the top request context via
+<cite>_request_ctx_stack.top</cite>. Extensions should use the top context and not the
+<cite>g</cite> object to store things like database connections.</li>
+<li>Finally, we add a <cite>get_db</cite> function that simplifies access to the context&#8217;s
+database.</li>
+</ol>
+<p>So why did we decide on a class based approach here? Because using our
+extension looks something like this:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
+<span class="kn">from</span> <span class="nn">flask_sqlite3</span> <span class="kn">import</span> <span class="n">SQLite3</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
+<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_pyfile</span><span class="p">(</span><span class="s">&#39;the-config.cfg&#39;</span><span class="p">)</span>
+<span class="n">manager</span> <span class="o">=</span> <span class="n">SQLite3</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+<span class="n">db</span> <span class="o">=</span> <span class="n">manager</span><span class="o">.</span><span class="n">get_db</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>You can then use the database from views like this:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_all</span><span class="p">():</span>
+ <span class="n">cur</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+ <span class="n">cur</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Opening a database connection from outside a view function is simple.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">yourapplication</span> <span class="kn">import</span> <span class="n">db</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">cur</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">cur</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="adding-an-init-app-function">
+<h2>Adding an <cite>init_app</cite> Function<a class="headerlink" href="#adding-an-init-app-function" title="Permalink to this headline">¶</a></h2>
+<p>In practice, you&#8217;ll almost always want to permit users to initialize your
+extension and provide an app object after the fact. This can help avoid
+circular import problems when a user is breaking their app into multiple files.
+Our extension could add an <cite>init_app</cite> function as follows:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">SQLite3</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+
+ <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+ <span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="p">)</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="bp">None</span>
+
+ <span class="k">def</span> <span class="nf">init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;SQLITE3_DATABASE&#39;</span><span class="p">,</span> <span class="s">&#39;:memory:&#39;</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">teardown_request</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">teardown_request</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">before_request</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">before_request</span><span class="p">)</span>
+
+ <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="k">return</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s">&#39;SQLITE3_DATABASE&#39;</span><span class="p">])</span>
+
+ <span class="k">def</span> <span class="nf">before_request</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">teardown_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">get_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="k">if</span> <span class="n">ctx</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
+ <span class="k">return</span> <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span>
+</pre></div>
+</div>
+<p>The user could then initialize the extension in one file:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">manager</span> <span class="o">=</span> <span class="n">SQLite3</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>and bind their app to the extension in another file:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">manager</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="end-of-request-behavior">
+<h2>End-Of-Request Behavior<a class="headerlink" href="#end-of-request-behavior" title="Permalink to this headline">¶</a></h2>
+<p>Due to the change in Flask 0.7 regarding functions that are run at the end
+of the request your extension will have to be extra careful there if it
+wants to continue to support older versions of Flask. The following
+pattern is a good way to support both:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">close_connection</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
+ <span class="n">ctx</span> <span class="o">=</span> <span class="n">_request_ctx_stack</span><span class="o">.</span><span class="n">top</span>
+ <span class="n">ctx</span><span class="o">.</span><span class="n">sqlite3_db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+ <span class="k">return</span> <span class="n">response</span>
+
+<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="s">&#39;teardown_request&#39;</span><span class="p">):</span>
+ <span class="n">app</span><span class="o">.</span><span class="n">teardown_request</span><span class="p">(</span><span class="n">close_connection</span><span class="p">)</span>
+<span class="k">else</span><span class="p">:</span>
+ <span class="n">app</span><span class="o">.</span><span class="n">after_request</span><span class="p">(</span><span class="n">close_connection</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Strictly speaking the above code is wrong, because teardown functions are
+passed the exception and typically don&#8217;t return anything. However because
+the return value is discarded this will just work assuming that the code
+in between does not touch the passed parameter.</p>
+</div>
+<div class="section" id="learn-from-others">
+<h2>Learn from Others<a class="headerlink" href="#learn-from-others" title="Permalink to this headline">¶</a></h2>
+<p>This documentation only touches the bare minimum for extension
+development. If you want to learn more, it&#8217;s a very good idea to check
+out existing extensions on the <a class="reference external" href="http://flask.pocoo.org/extensions/">Flask Extension Registry</a>. If you feel
+lost there is still the <a class="reference external" href="http://flask.pocoo.org/mailinglist/">mailinglist</a> and the <a class="reference external" href="http://flask.pocoo.org/community/irc/">IRC channel</a> to get some
+ideas for nice looking APIs. Especially if you do something nobody before
+you did, it might be a very good idea to get some more input. This not
+only to get an idea about what people might want to have from an
+extension, but also to avoid having multiple developers working on pretty
+much the same side by side.</p>
+<p>Remember: good API design is hard, so introduce your project on the
+mailinglist, and let other developers give you a helping hand with
+designing the API.</p>
+<p>The best Flask extensions are extensions that share common idioms for the
+API. And this can only work if collaboration happens early.</p>
+</div>
+<div class="section" id="approved-extensions">
+<h2>Approved Extensions<a class="headerlink" href="#approved-extensions" title="Permalink to this headline">¶</a></h2>
+<p>Flask also has the concept of approved extensions. Approved extensions
+are tested as part of Flask itself to ensure extensions do not break on
+new releases. These approved extensions are listed on the <a class="reference external" href="http://flask.pocoo.org/extensions/">Flask
+Extension Registry</a> and marked appropriately. If you want your own
+extension to be approved you have to follow these guidelines:</p>
+<ol class="arabic simple">
+<li>An approved Flask extension must provide exactly one package or module
+named <tt class="docutils literal"><span class="pre">flask_extensionname</span></tt>. They might also reside inside a
+<tt class="docutils literal"><span class="pre">flaskext</span></tt> namespace packages though this is discouraged now.</li>
+<li>It must ship a testing suite that can either be invoked with <tt class="docutils literal"><span class="pre">make</span> <span class="pre">test</span></tt>
+or <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">test</span></tt>. For test suites invoked with <tt class="docutils literal"><span class="pre">make</span>
+<span class="pre">test</span></tt> the extension has to ensure that all dependencies for the test
+are installed automatically, in case of <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">test</span></tt>
+dependencies for tests alone can be specified in the <cite>setup.py</cite>
+file. The test suite also has to be part of the distribution.</li>
+<li>APIs of approved extensions will be checked for the following
+characteristics:<ul>
+<li>an approved extension has to support multiple applications
+running in the same Python process.</li>
+<li>it must be possible to use the factory pattern for creating
+applications.</li>
+</ul>
+</li>
+<li>The license must be BSD/MIT/WTFPL licensed.</li>
+<li>The naming scheme for official extensions is <em>Flask-ExtensionName</em> or
+<em>ExtensionName-Flask</em>.</li>
+<li>Approved extensions must define all their dependencies in the
+<cite>setup.py</cite> file unless a dependency cannot be met because it is not
+available on PyPI.</li>
+<li>The extension must have documentation that uses one of the two Flask
+themes for Sphinx documentation.</li>
+<li>The setup.py description (and thus the PyPI description) has to
+link to the documentation, website (if there is one) and there
+must be a link to automatically install the development version
+(<tt class="docutils literal"><span class="pre">PackageName==dev</span></tt>).</li>
+<li>The <tt class="docutils literal"><span class="pre">zip_safe</span></tt> flag in the setup script must be set to <tt class="docutils literal"><span class="pre">False</span></tt>,
+even if the extension would be safe for zipping.</li>
+<li>An extension currently has to support Python 2.5, 2.6 as well as
+Python 2.7</li>
+</ol>
+</div>
+<div class="section" id="extension-import-transition">
+<span id="ext-import-transition"></span><h2>Extension Import Transition<a class="headerlink" href="#extension-import-transition" title="Permalink to this headline">¶</a></h2>
+<p>For a while we recommended using namespace packages for Flask extensions.
+This turned out to be problematic in practice because many different
+competing namespace package systems exist and pip would automatically
+switch between different systems and this caused a lot of problems for
+users.</p>
+<p>Instead we now recommend naming packages <tt class="docutils literal"><span class="pre">flask_foo</span></tt> instead of the now
+deprecated <tt class="docutils literal"><span class="pre">flaskext.foo</span></tt>. Flask 0.8 introduces a redirect import
+system that lets uses import from <tt class="docutils literal"><span class="pre">flask.ext.foo</span></tt> and it will try
+<tt class="docutils literal"><span class="pre">flask_foo</span></tt> first and if that fails <tt class="docutils literal"><span class="pre">flaskext.foo</span></tt>.</p>
+<p>Flask extensions should urge users to import from <tt class="docutils literal"><span class="pre">flask.ext.foo</span></tt>
+instead of <tt class="docutils literal"><span class="pre">flask_foo</span></tt> or <tt class="docutils literal"><span class="pre">flaskext_foo</span></tt> so that extensions can
+transition to the new package name without affecting users.</p>
+</div>
+</div>
+
+
+ </div>
+ </div>
+ </div>
+ <div class="sphinxsidebar">
+ <div class="sphinxsidebarwrapper"><p class="logo"><a href="index.html">
+ <img class="logo" src="_static/flask.png" alt="Logo"/>
+</a></p>
+ <h3><a href="index.html">Table Of Contents</a></h3>
+ <ul>
+<li><a class="reference internal" href="#">Flask Extension Development</a><ul>
+<li><a class="reference internal" href="#anatomy-of-an-extension">Anatomy of an Extension</a></li>
+<li><a class="reference internal" href="#hello-flaskext">&#8220;Hello Flaskext!&#8221;</a><ul>
+<li><a class="reference internal" href="#setup-py">setup.py</a></li>
+<li><a class="reference internal" href="#flask-sqlite3-py">flask_sqlite3.py</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#initializing-extensions">Initializing Extensions</a></li>
+<li><a class="reference internal" href="#the-extension-code">The Extension Code</a></li>
+<li><a class="reference internal" href="#adding-an-init-app-function">Adding an <cite>init_app</cite> Function</a></li>
+<li><a class="reference internal" href="#end-of-request-behavior">End-Of-Request Behavior</a></li>
+<li><a class="reference internal" href="#learn-from-others">Learn from Others</a></li>
+<li><a class="reference internal" href="#approved-extensions">Approved Extensions</a></li>
+<li><a class="reference internal" href="#extension-import-transition">Extension Import Transition</a></li>
+</ul>
+</li>
+</ul>
+<h3>Related Topics</h3>
+<ul>
+ <li><a href="index.html">Documentation overview</a><ul>
+ <li>Previous: <a href="unicode.html" title="previous chapter">Unicode in Flask</a></li>
+ <li>Next: <a href="styleguide.html" title="next chapter">Pocoo Styleguide</a></li>
+ </ul></li>
+</ul>
+ <h3>This Page</h3>
+ <ul class="this-page-menu">
+ <li><a href="_sources/extensiondev.txt"
+ rel="nofollow">Show Source</a></li>
+ </ul>
+<div id="searchbox" style="display: none">
+ <h3>Quick search</h3>
+ <form class="search" action="search.html" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="Go" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ Enter search terms or a module, class or function name.
+ </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+ </div>
+ </div>
+ <div class="clearer"></div>
+ </div>
+ <div class="footer">
+ &copy; Copyright 2010, Armin Ronacher.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
+ </div>
+ </body>
+</html> \ No newline at end of file