Commits

Anonymous committed c46ce64

manifest and other updates

  • Participants
  • Parent commits 9d86770

Comments (0)

Files changed (6)

 *.swp
 *.swo
 *.zip
+*.egg
+*.orig
 *~
 
 dist
+include LICENSE tests.py
+recursive-include docs *
+recursive-exclude docs *.pyc
+recursive-exclude docs *.pyo
+prune docs/_build
+prune docs/_themes/.git
-flask-script
+Flask-Script
 
-Description goes here
+A set of utilities for use with the Flask framework, which provide 
+decorators, classes and helpers for writing your own script commands.
+
+Useful for creating command-line scripts, cronjobs etc outside your
+web application.
+
+
+

docs/conf.py.orig

+# -*- coding: utf-8 -*-
+#
+# flask-testing documentation build configuration file, created by
+# sphinx-quickstart on Wed Jun 23 08:26:41 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.append(os.path.abspath('_themes'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Flask-Script'
+copyright = u'2010, Dan Jacob'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.2'
+# The full version, including alpha/beta/rc tags.
+release = '0.2'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+#pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'flask_small'
+
+html_theme_options = {
+     'index_logo': 'flask-script.png',
+     'github_fork': None
+}
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ['_themes']
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'flask-scriptdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'flask-script.tex', u'Flask-Script Documentation',
+   u'Dan Jacob', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'flask-script', u'Flask-Script Documentation',
+     [u'Dan Jacob'], 1)
+]

docs/index.rst.orig

+Flask-Script
+======================================
+
+.. module:: Flask-Script
+
+The **Flask-Script** extension provides support for writing external scripts in Flask. It uses `argparse`_ to parse command line arguments.
+
+You define and add commands that can be called from the command line to a ``Manager`` instance::
+
+    # manage.py
+    
+    from flaskext.script import Manager
+
+    from myapp import app
+
+    manager = Manager(app)
+    
+    @manager.command
+    def hello(app):
+        print "hello"
+
+    if __name__ == "__main__":
+        manager.run()
+
+Then run the script like this::
+
+    python manage.py hello
+    > hello
+    
+Source code and issue tracking at `Bitbucket`_.
+
+Installing Flask-Script
+------------------------
+
+Install with **pip** and **easy_install**::
+
+    pip install Flask-Script
+
+or download the latest version from Bitbucket::
+
+    hg clone http://bitbucket.org/danjac/flask-script
+
+    cd flask-script
+
+    python setup.py develop
+
+If you are using **virtualenv**, it is assumed that you are installing **Flask-Script**
+in the same virtualenv as your Flask application(s).
+
+Creating and running commands
+-----------------------------
+
+The first step is to create a Python module to run your script commands in. You can call it
+anything you like, for our examples we'll call it **manage.py**.
+
+You don't have to place all your commands in the same file; for example, in a larger project
+with lots of commands you might want to split them into a number of files with related commands.
+
+In your **manage.py** file you have to create a ``Manager`` instance. The ``Manager`` class
+keeps track of all the commands and handles how they are called from the command line::
+
+    from flaskext.script import Manager
+
+    app = Flask(__name__)
+    # configure your app
+
+    manager = Manager(app)
+
+    if __name__ == "__main__":
+        manager.run()
+
+Calling ``manager.run()`` prepares your ``Manager`` instance to receive input from the command line.
+
+The ``Manager`` requires a single argument, a **Flask** instance. This may also be a function or callable
+that returns a **Flask** instance instead, if you want to use a factory pattern.
+
+The next step is to create and add your commands. There are three methods for creating commands:
+
+    * subclassing the ``Command`` class
+    * using the ``@command`` decorator
+    * using the ``@option`` decorator
+
+To take a very simple example, we want to create a ``Print`` command that just prints out "hello world". It 
+doesn't take any arguments so is very straightforward::
+
+    from flaskext.script import Command
+
+    class Print(Command):
+
+        description = "prints hello world"
+
+        def run(self, app):
+            print "hello world"
+
+Now the command needs to be added to our ``Manager`` instance, created above::
+
+    manager.add_command('print', Print())
+
+This of course needs to be called before ``manager.run``. Now in our command line::
+
+    python manage.py print
+    > hello world
+
+You can also pass the ``Command`` instance in a dict to ``manager.run()``::
+
+    manager.run({'print' : Print()})
+
+The first argument to your ``run`` command, other than ``self``, is always ``app``: this is the Flask
+application instance provided by the ``app`` passed to the ``Manager``. Additional arguments
+are configured through the ``option_list`` (see below).
+
+To get a list of available commands and their descriptions, just run with no command::
+
+    python manage.py
+
+To get help text for a particular command::
+
+    python manage.py runserver -h
+
+This will print usage plus the docstring of the ``Command``.
+
+The next method is using the ``@command`` decorator, which belongs to the ``Manager`` instance. 
+
+This is probably the easiest to use, when you have a simple command::
+
+    @manager.command
+    def hello(app):
+        "Just say hello"
+        print "hello"
+
+Commands created this way are run in exactly the same way as those created with the ``Command`` class::
+
+    python manage.py hello
+    > hello
+
+As with the ``Command`` class, the docstring you use for the function will appear when you run with the **-h** option::
+
+    python manage.py -h
+    > Just say hello
+
+Finally, the ``@option`` decorator, again belonging to ``Manager`` can be used when you want more sophisticated 
+control over your commands::
+
+    @manager.option('-n', '--name', help='Your name')
+    def hello(app, name):
+        print "hello", name
+
+The ``@option`` command takes the exact same arguments as the ``Option`` instance - see the section on adding arguments
+to commands below.
+
+Note that with ``@command`` and ``@option`` decorators, the function must take the Flask application instance as the first
+argument, just as with ``Command.run``.
+
+Adding arguments to commands
+----------------------------
+
+Most commands take a number of named or positional arguments that you pass in the command line.
+
+Taking the above examples, rather than just print "hello world" we would like to be able to print some
+arbitrary name, like this::
+
+    python manage.py hello --name=Joe
+    hello Joe
+
+or alternatively::
+
+    python manage.py hello -n Joe
+
+To facilitate this you use the ``option_list`` attribute of the ``Command`` class::
+
+    from flaskext.script import Command, Manager, Option
+
+    class Hello(Command):
+
+        option_list = (
+            Option('--name', '-n', dest='name'),
+        )
+
+        def run(self, app, name):
+            print "hello %s" % name
+
+Positional and optional arguments are stored as ``Option`` instances - see the API below for details.
+
+Alternatively, you can define a ``get_options`` method for your ``Command`` class. This is useful if you want to be able
+to return options at runtime based on for example per-instance attributes::
+
+    class Hello(Command):
+
+        def __init__(self, default_name='Joe'):
+            self.default_name=default_name
+
+        def get_options(self):
+            return [
+                Option('-n', '--name', dest='name', default=self.default_name),
+            ]
+
+        def run(self, app, name):
+            print "hello",  name
+
+If you are using the ``@command`` decorator, it's much easier - the options are extracted automatically from your function arguments::
+
+    @manager.command
+    def hello(app, name):
+        print "hello", name
+
+
+Then do::
+
+    > python manage.py hello Joe
+    hello joe
+
+Or you can do optional arguments::
+
+    @manager.command
+    def hello(app, name="Fred")
+        print hello, name
+
+These can be called like this::
+
+    > python manage.py hello --name=Joe
+    hello Joe
+
+alternatively::
+    
+    > python manage.py hello -n Joe
+    hello Joe
+
+
+and if you don't pass in any argument::
+
+    > python manage.py hello 
+    hello Fred
+
+There are a couple of important points to note here.
+
+The short-form **-n** is formed from the first letter of the argument, so "name" > "-n". Therefore it's a good idea that your
+optional argument variable names begin with different letters ("app" is ignored, so don't worry about "a" being taken).
+
+The second issue is that the **-h** switch always runs the help text for that command, so avoid arguments starting with the letter "h".
+
+Note also that if your optional argument is a boolean, for example::
+
+    @manage.command
+    def verify(app, verified=False):
+        """
+        Checks if verified
+        """
+        print "VERIFIED?", "YES" if verified else "NO"
+
+You can just call it like this::
+
+    > python manage.py verify
+    VERIFIED? NO
+
+    > python manage.py verify -v
+    VERIFIED? YES
+
+    > python manage.py verify --verified
+    VERIFIED? YES
+
+For more complex options it's better to use the ``@option`` decorator::
+
+    @manager.option('-n', '--name', dest='name', default='joe')
+    def hello(app, name):
+        print "hello", name
+
+You can add as many options as you want::
+
+    @manager.option('-n', '--name', dest='name', default='joe')
+    @manager.option('-u', '--url', dest='url', default=None)
+    def hello(app, name, url):
+        if url is None:
+            print "hello", name
+        else:
+            print "hello", name, "from", url
+
+This can be called like so::
+
+    > python manage.py hello -n Joe -u reddit.com
+    hello Joe from reddit.com
+
+or like this::
+    
+    > python manage.py hello --name=Joe --url=reddit.com
+    hello Joe from reddit.com
+
+Adding options to the manager
+-----------------------------
+
+Options can also be passed to the ``Manager`` instance. This is allows you to set up options that are passed to the application rather
+than a single command. For example, you might want to have a flag to set the configuration file for your application::
+
+    def create_app(config=None):
+        
+        app = Flask(__name__)
+        if config is not None:
+            app.config.from_pyfile(config)
+        # configure your app...
+        return app
+
+In order to pass that ``config`` argument, use the ``add_option()`` method of your ``Manager`` instance. It takes the same arguments
+as ``Option``::
+
+    manager.add_option('-c', '--config', dest='config', required=False)
+
+Suppose you have this command::
+    
+    @manager.command
+    def hello(app, name):
+        uppercase = app.config.get('USE_UPPERCASE', False)
+        if uppercase:
+            name = name.upper()
+        print hello, name
+
+You can now run the following::
+
+    > python manage.py hello joe -c dev.cfg
+    hello JOE
+
+Assuming the ``USE_UPPERCASE`` setting is **True** in your dev.cfg file.
+
+Notice also that the "config" option is **not** passed to the command.
+
+In order for manager options to work it is assumed that you are passing a factory function, rather than a Flask instance, to your 
+``Manager`` constructor.
+
+Getting user input
+------------------
+
+**Flask-Script** comes with a set of helper functions for grabbing user input from the command line. For example::
+    
+    from flaskext.script import Manager, prompt_bool
+    
+    from myapp import app
+    from myapp.models import db
+
+    manager = Manager(app)
+        
+    @manager.command
+    def dropdb(app):
+        if prompt_bool(
+            "Are you sure you want to lose all your data"):
+            db.drop_all()
+
+It then runs like this::
+
+    python manage.py dropdb
+    > Are you sure you want to lose all your data ? [N]
+
+Default commands
+----------------
+
+**Flask-Script** has a couple of ready commands you can add and customize: ``Server`` and ``Shell``.
+
+The ``Server`` command runs the **Flask** development server. It takes an optional ``port`` argument (default **5000**)::
+
+    from flaskext.script import Server, Manager
+    from myapp import create_app
+
+    manager = Manager(create_app)
+    manager.add_command("runserver", Server())
+
+    if __name__ == "__main__":
+        manager.run()
+
+and then run the command::
+
+    python manage.py runserver
+
+The ``Server`` command has a number of command-line arguments - run ``python manage.py runserver -h`` for details on these.
+
+Needless to say the development server is not intended for production use.
+
+The ``Shell`` command starts a Python shell. You can pass in a ``make_context`` argument, which must be a ``callable`` returning a ``dict``. By default, this is just a dict returning the ``app`` instance::
+
+    from flaskext.script import Shell, Manager
+    
+    from myapp import app
+    from myapp import models
+    from myapp.models import db
+
+    def _make_context(app):
+        return dict(app=app, db=db, models=models)
+
+    manager = Manager(create_app)
+    manager.add_command("shell", Shell(make_context=_make_context))
+    
+This is handy if you want to include a bunch of defaults in your shell to save typing lots of ``import`` statements.
+
+The ``Shell`` command will use `IPython <http://ipython.scipy.org/moin/>`_ if it is installed, otherwise it defaults to the standard Python shell. You can disable this behaviour in two ways: by passing the ``use_ipython`` argument to the ``Shell`` constructor, or passing the flag ``--no-ipython`` in the command line. 
+
+The default commands **shell** and **runserver** are included by default, with the default options for these commands. If you wish to 
+replace them with different commands simply override with ``add_command()`` or the decorators. If you pass ``with_default_commands=False``
+to the ``Manager`` constructor these commands will not be loaded::
+
+    manager = Manager(app, with_default_commands=False)
+
+
+Accessing local proxies
+-----------------------
+
+The ``Manager`` runs the command inside a `Flask test context <http://flask.pocoo.org/docs/testing/#other-testing-tricks>`_. This means thathat you can access request-local proxies where appropriate, such as ``current_app``, which may be used by extensions.
+
+API
+---
+
+.. module:: flaskext.script
+
+.. autoclass:: Manager
+   :members:
+    
+.. autoclass:: Command
+   :members:
+
+.. autoclass:: Shell
+
+.. autoclass:: Server
+
+.. class:: Option
+
+    Stores option parameters for `argparse.ArgumentParser.add_argument <http://pypi.python.org/pypi/argparse>`_. Use with ``Command.option_list`` or ``Command.get_options()``. 
+
+    .. method:: __init__(name_or_flags, action, nargs, const, default, type, choices, required, help, metavar, dest)
+
+        :param name_or_flags: Either a name or a list of option strings, e.g. foo or -f, --foo
+        :param action: The basic type of action to be taken when this argument is encountered at the command-line.
+        :param nargs: The number of command-line arguments that should be consumed.
+        :param const: A constant value required by some action and nargs selections.
+        :param default: The value produced if the argument is absent from the command-line.
+        :param type: The type to which the command-line arg should be converted.
+        :param choices: A container of the allowable values for the argument.
+        :param required: Whether or not the command-line option may be omitted (optionals only).
+        :param help: A brief description of what the argument does.
+        :param metavar: A name for the argument in usage messages.
+        :param dest: The name of the attribute to be added to the object returned by parse_args().
+
+.. autofunction:: prompt
+
+.. autofunction:: prompt_bool
+
+.. autofunction:: prompt_pass
+
+.. autofunction:: prompt_choices
+
+.. _Flask: http://flask.pocoo.org
+.. _Bitbucket: http://bitbucket.org/danjac/flask-script
+.. _argparse: http://pypi.python.org/pypi/argparse

flaskext/script.py.orig

+# -*- coding: utf-8 -*-
+<<<<<<< local
+=======
+from __future__ import absolute_import
+>>>>>>> other
+from __future__ import with_statement
+
+import sys
+import code
+import string
+import getpass
+import inspect
+import warnings
+
+import argparse
+
+from flask import Flask, _request_ctx_stack
+
+__all__ = ["Command", "Shell", "Server", "Manager", "Option",
+           "prompt", "prompt_pass", "prompt_bool", "prompt_choices"]
+
+def prompt(name, default=None):
+    
+    """
+    Grab user input from command line.
+
+    :param name: prompt text
+    :param default: default value if no input provided.
+    """
+
+    prompt = name + (default and ' [%s]' % default or '')
+    prompt += name.endswith('?') and ' ' or ': '
+    while True:
+        rv = raw_input(prompt)
+        if rv:
+            return rv
+        if default is not None:
+            return default
+
+
+def prompt_pass(name, default=None):
+
+    """
+    Grabs hidden (password) input from command line.
+
+    :param name: prompt text
+    :param default: default value if no input provided.
+    """
+
+    prompt = name + (default and ' [%s]' % default or '')
+    prompt += name.endswith('?') and ' ' or ': '
+    while True:
+        rv = getpass.getpass(prompt)
+        if rv:
+            return rv
+        if default is not None:
+            return default
+
+
+def prompt_bool(name, default=False, yes_choices=None, no_choices=None):
+    
+    """
+    Grabs user input from command line and converts to boolean
+    value.
+
+    :param name: prompt text
+    :param default: default value if no input provided.
+    :param yes_choices: default 'y', 'yes', '1', 'on', 'true', 't'
+    :param no_choices: default 'n', 'no', '0', 'off', 'false', 'f'
+    """
+
+    yes_choices = yes_choices or ('y', 'yes', '1', 'on', 'true', 't')
+    no_choices = no_choices or ('n', 'no', '0', 'off', 'false', 'f')
+    
+    while True:
+        rv = prompt(name + '?', default and yes_choices[0] or no_choices[0])
+        if not rv:
+            return default
+        if rv.lower() in yes_choices:
+            return True
+        elif rv.lower() in no_choices:
+            return False
+
+
+def prompt_choices(name, choices, default=None, 
+    resolve=string.lower, no_choice=('none',)):
+    
+    """
+    Grabs user input from command line from set of provided choices.
+
+    :param name: prompt text
+    :param choices: list or tuple of available choices. Choices may be 
+                    single strings or (key, value) tuples.
+    :param default: default value if no input provided.
+    :param no_choice: acceptable list of strings for "null choice"
+    """
+    
+    _choices = []
+    options = []
+    
+    for choice in choices:
+        if isinstance(choice, basestring):
+            options.append(choice)
+        else:
+            options.append("%s [%s]" % (choice[1], choice[0]))
+            choice = choice[0]
+        _choices.append(choice)
+
+    while True:
+        rv = prompt(name + '? - (%s)' % ', '.join(options), default)
+        if not rv:
+            return default
+        rv = resolve(rv)
+        if rv in no_choice:
+            return None
+        if rv in _choices:
+            return rv
+
+
+class Option(object):
+
+    """
+    Stores positional and optional arguments for `ArgumentParser.add_argument 
+    <http://argparse.googlecode.com/svn/trunk/doc/add_argument.html>`_.
+
+    :param name_or_flags: Either a name or a list of option strings, 
+                          e.g. foo or -f, --foo
+    :param action: The basic type of action to be taken when this argument 
+                   is encountered at the command-line.
+    :param nargs: The number of command-line arguments that should be consumed.
+    :param const: A constant value required by some action and nargs selections.
+    :param default: The value produced if the argument is absent from 
+                    the command-line.
+    :param type: The type to which the command-line arg should be converted.
+    :param choices: A container of the allowable values for the argument.
+    :param required: Whether or not the command-line option may be omitted 
+                     (optionals only).
+    :param help: A brief description of what the argument does.
+    :param metavar: A name for the argument in usage messages.
+    :param dest: The name of the attribute to be added to the object 
+                 returned by parse_args().
+    """
+    
+    def __init__(self, *args, **kwargs):
+        self.args = args
+        self.kwargs = kwargs
+
+
+class Command(object):
+    
+    """
+    Base class for creating commands.
+    """
+
+    option_list = []
+
+    @property
+    def description(self):
+        description = self.__doc__ or ''
+        return description.strip()
+
+    def add_option(self, option):
+        
+        """
+        Adds Option to option list.
+        """
+        
+        self.option_list.append(option)
+
+    def get_options(self):
+
+        """
+        By default, returns self.option_list.Override if you
+        need to do instance-specific configuration.
+        """
+
+        return self.option_list
+
+
+    def create_parser(self, prog):
+        parser = argparse.ArgumentParser(prog=prog,
+                                         description=self.description)
+
+        for option in self.get_options():
+            parser.add_argument(*option.args, **option.kwargs)   
+        
+        return parser
+
+    def run(self):
+
+        """
+        Runs a command. This must be implemented by the subclass. The first
+        argument is always the app (Flask instance) followed by arguments
+        as configured by the Command options.
+        """
+
+        raise NotImplementedError
+
+    def prompt(self, name, default=None):
+        warnings.warn_explicit(
+            "Command.prompt is deprecated, use prompt() function instead")
+
+        prompt(name, default)
+
+    def prompt_pass(self, name, default=None):
+        warnings.warn_explicit(
+            "Command.prompt_pass is deprecated, use prompt_pass() function instead")
+
+        prompt_pass(name, default)
+
+    def prompt_bool(self, name, default=False):
+        warnings.warn_explicit(
+            "Command.prompt_bool is deprecated, use prompt_bool() function instead")
+
+        prompt_bool(name, default)
+
+    def prompt_choices(self, name, choices, default=None):
+        warnings.warn_explicit(
+            "Command.choices is deprecated, use prompt_choices() function instead")
+
+        prompt_choices(name, choices, default)
+
+class Shell(Command):
+
+    """
+    Runs a Python shell inside Flask application context.
+
+    :param banner: banner appearing at top of shell when started
+    :param make_context: a callable returning a dict of variables 
+                         used in the shell namespace. The callable 
+                         takes a single argument, "app", the Flask 
+                         instance. By default returns a dict consisting
+                         of just the app.
+    :param use_ipython: use IPython shell if available, ignore if not. 
+                        The IPython shell can be turned off in command 
+                        line by passing the **--no-ipython** flag.
+    """
+
+    banner = ''
+
+    description = 'Runs a Python shell inside Flask application context.'
+    
+    def __init__(self, banner=None, make_context=None, use_ipython=True):
+
+
+        self.banner = banner or self.banner
+        self.use_ipython = use_ipython
+
+        if make_context is None:
+            make_context = lambda: dict(app=_request_ctx_stack.top.app)
+
+        self.make_context = make_context
+    
+    def get_options(self):
+
+        return (
+                Option('--no-ipython',
+                       action="store_true",
+                       dest='no_ipython',
+                       default=not(self.use_ipython)),)
+
+    def get_context(self):
+        
+        """
+        Returns a dict of context variables added to the shell namespace.
+        """
+
+        return self.make_context()
+
+    def run(self, no_ipython):
+
+        """
+        Runs the shell. Unless no_ipython is True or use_python is False
+        then runs IPython shell if that is installed.
+        """
+
+        context = self.get_context()
+        if not no_ipython:
+            try:
+                import IPython
+                sh = IPython.Shell.IPShellEmbed(banner=self.banner)
+                sh(global_ns=dict(), local_ns=context)
+                return
+            except ImportError:
+                pass
+
+        code.interact(self.banner, local=context)
+
+
+class Server(Command):
+
+    """
+    Runs the Flask development server i.e. app.run()
+
+    :param host: server host
+    :param port: server port
+    :param use_debugger: if False, will no longer use Werkzeug debugger.
+                         This can be overriden in the command line 
+                         by passing the **-d** flag.
+    :param use_reloader: if False, will no longer use auto-reloader.
+                         This can be overriden in the command line by 
+                         passing the **-r** flag.
+                         
+    """
+
+    description = 'Runs the Flask development server i.e. app.run()'
+
+    def __init__(self, host='127.0.0.1', port=5000, use_debugger=True,
+        use_reloader=True):
+
+
+        self.port = port
+        self.host = host
+        self.use_debugger = use_debugger
+        self.use_reloader = use_reloader
+    
+    def get_options(self):
+
+        return (
+                Option('-t', '--host',
+                       dest='host',
+                       default=self.host),
+
+                Option('-p', '--port', 
+                       dest='port', 
+                       type=int,
+                       default=self.port),
+
+                Option('-d', '--debug',
+                       action='store_true',
+                       dest='use_debugger',
+                       default=self.use_debugger),
+        
+                Option('-r', '--reload',
+                       action='store_true',
+                       dest='use_reloader',
+                       default=self.use_reloader))
+
+    def run(self, host, port, use_debugger, use_reloader):
+        app = _request_ctx_stack.top.app
+        app.run(host=host,
+                port=port,
+                debug=use_debugger,
+                use_debugger=use_debugger,
+                use_reloader=use_reloader)
+
+
+class InvalidCommand(Exception):
+    pass
+
+
+class Manager(object):
+
+    """
+    Controller class for handling a set of commands.
+
+    Typical usage::
+        
+        class Print(Command):
+
+            def run(self, app):
+                print "hello"
+
+        app = Flask(__name__)
+        
+        manager = Manager(app)
+        manager.add_command("print", Print())
+        
+        if __name__ == "__main__":
+            manager.run()
+
+    On command line::
+
+        python manage.py print
+        > hello
+
+    :param app: Flask instance or callable returning a Flask instance.
+    :param with_default_commands: load commands **runserver** and **shell**
+                                  by default.
+    """
+
+    def __init__(self, app, with_default_commands=True):
+
+        self.app = app
+
+        self._commands = dict()
+        self._options = list()
+        
+        if with_default_commands:
+            self.add_default_commands()
+
+    def add_default_commands(self):
+        """
+        Adds the shell and runserver default commands. To override these 
+        simply add your own equivalents using add_command or decorators.
+        """
+
+        self.add_command("shell", Shell())
+        self.add_command("runserver", Server())
+
+    def create_app(self, **kwargs):
+
+        if isinstance(self.app, Flask):
+            return self.app
+
+        return self.app(**kwargs)
+
+    def create_parser(self, prog):
+
+        """
+        Creates an ArgumentParser instance from options returned 
+        by get_options(), and a subparser for the given command.
+        """
+
+        parser = argparse.ArgumentParser(prog=prog)
+        for option in self.get_options():
+            parser.add_argument(*option.args, **option.kwargs)
+        
+        return parser
+
+    def get_options(self):
+        return self._options
+
+    def add_option(self, *args, **kwargs):
+        """
+        Adds an application-wide option. This is useful if you want to set variables
+        applying to the application setup, rather than individual commands.
+
+        For this to work, the manager must be initialized with a factory
+        function rather than an instance. Otherwise any options you set will
+        be ignored.
+
+        The arguments are then passed to your function, e.g.::
+
+            def create_app(config=None):
+                app = Flask(__name__)
+                if config:
+                    app.config.from_pyfile(config)
+
+                return app
+
+            manager = Manager(create_app)
+            manager.add_option("-c", "--config", dest="config", required=False)
+            
+            > python manage.py -c dev.cfg mycommand
+
+        Any manager options passed in the command line will not be passed to 
+        the command.
+
+        Arguments for this function are the same as for the Option class.
+        """
+        
+        self._options.append(Option(*args, **kwargs))
+
+    def command(self, func):
+        """
+        Adds a command function to the registry.
+        
+        :param func: command function. Should take at least one argument, the 
+                     Flask application. Additional arguments depend on the 
+                     options.
+        
+        """
+            
+        args, varargs, keywords, defaults = inspect.getargspec(func)
+        
+        options = []
+
+        # first arg is always "app" : ignore
+
+        defaults = defaults or []
+        kwargs = dict(zip(*[reversed(l) for l in (args, defaults)]))
+
+        for arg in args:
+            if arg in kwargs:
+                
+                default=kwargs[arg]
+
+                if isinstance(default, bool):
+                    options.append(Option('-%s' % arg[0],
+                                          '--%s' % arg,
+                                          action="store_true",
+                                          dest=arg,
+                                          required=False,
+                                          default=default))
+                else:
+                    options.append(Option('-%s' % arg[0],
+                                          '--%s' % arg,
+                                          dest=arg,
+                                          required=False,
+                                          default=default))
+        
+            else:
+                options.append(Option(arg))
+
+
+        command = Command()
+        command.run = func
+        command.__doc__ = func.__doc__
+        command.option_list = options
+
+        self.add_command(func.__name__, command)
+
+        return func
+    
+    def shell(self, func):
+        """
+        Decorator that wraps function in shell command. This is equivalent to::
+            
+            def _make_context(app):
+                return dict(app=app)
+
+            manager.add_command("shell", Shell(make_context=_make_context))
+
+        The decorated function should take a single "app" argument, and return 
+        a dict.
+
+        For more sophisticated usage use the Shell class.
+        """
+
+        self.add_command('shell', Shell(make_context=func))
+
+        return func
+
+    def option(self, *args, **kwargs):
+        
+        """
+        Decorator to add an option to a function. Automatically registers the 
+        function - do not use together with ``@command``. You can add as many
+        ``@option`` calls as you like, for example::
+
+            @option('-n', '--name', dest='name')
+            @option('-u', '--url', dest='url')
+            def hello(app, name, url):
+                print "hello", name, url
+
+        Takes the same arguments as the ``Option`` constructor.
+        """
+
+        option = Option(*args, **kwargs)
+
+        def decorate(func):
+            name = func.__name__
+            
+            if name not in self._commands:
+            
+                command = Command()
+                command.run = func
+                command.__doc__ = func.__doc__
+                command.option_list = []
+
+                self.add_command(name, command)
+
+            self._commands[name].option_list.append(option)
+            return func
+        return decorate
+
+    def add_command(self, name, command):
+
+        """
+        Adds command to registry.
+
+        :param command: Command instance
+        """
+
+        self._commands[name] = command
+
+    def get_usage(self):
+        
+        """
+        Returns string consisting of all commands and their
+        descriptions.
+        """
+
+        rv = []
+
+        for name, command in self._commands.iteritems():
+            usage = name
+            description = command.description
+            if description:
+                usage += ": " + description
+            rv.append(usage)
+
+        return "\n".join(rv)
+    
+    def print_usage(self):
+        
+        """
+        Prints result of get_usage()
+        """
+
+        print self.get_usage()
+
+    def handle(self, prog, name, args=None):
+
+        args = list(args or [])
+
+        try:
+            command = self._commands[name]
+        except KeyError:
+            raise InvalidCommand, "Command %s not found" % name
+
+        help_args = ('-h', '--help')
+
+        # remove -h from args if present, and add to remaining args
+        app_args = [a for a in args if a not in help_args]
+
+        app_parser = self.create_parser(prog)
+        app_namespace, remaining_args = app_parser.parse_known_args(app_args)
+
+        for arg in help_args:
+            if arg in args:
+                remaining_args.append(arg)
+
+        command_parser = command.create_parser(prog + " " + name)
+        command_namespace = command_parser.parse_args(remaining_args)
+        
+        app = self.create_app(**app_namespace.__dict__)
+
+        with app.test_request_context():
+            command.run(**command_namespace.__dict__)
+
+    def run(self, commands=None):
+        
+        """
+        Prepares manager to receive command line input. Usually run
+        inside "if __name__ == "__main__" block in a Python script.
+
+        :param commands: optional dict of commands. Appended to any commands 
+                         added using add_command().
+        """
+
+        if commands:
+            self._commands.update(commands)
+        
+        try:
+            self.handle(sys.argv[0],
+                        sys.argv[1],
+                        sys.argv[2:])
+            
+            sys.exit(0)
+
+        except IndexError:
+            self.print_usage()
+            sys.exit(0)
+        
+        except InvalidCommand, e:
+            print e
+            self.print_usage()
+
+        sys.exit(1)
+
+