[Python-modules-commits] [flask-script] 01/06: Import flask-script_2.0.5.orig.tar.gz

Orestis Ioannou oorestisime-guest at moszumanska.debian.org
Tue Feb 23 09:25:56 UTC 2016


This is an automated email from the git hooks/post-receive script.

oorestisime-guest pushed a commit to branch master
in repository flask-script.

commit 2fc9654cc838e3dc3f527ab8b3aa3f9685e836d0
Author: Orestis Ioannou <orestis at oioannou.com>
Date:   Thu Feb 18 05:09:23 2016 +0100

    Import flask-script_2.0.5.orig.tar.gz
---
 Flask_Script.egg-info/PKG-INFO    |  12 +--
 Flask_Script.egg-info/SOURCES.txt |   3 -
 LICENSE                           |   1 +
 PKG-INFO                          |  12 +--
 README.rst                        |   8 +-
 docs/.DS_Store                    | Bin 6148 -> 0 bytes
 docs/_static/index.zip            | Bin 435 -> 0 bytes
 docs/conf.py                      |   2 +-
 docs/index.rst                    | 198 ++++++++++++++++++++++++++++------
 flask_script/__init__.py          | 217 ++++++++++++++++++--------------------
 flask_script/commands.py          | 200 ++++++++++++++++++++++-------------
 setup.cfg                         |   8 --
 setup.py                          |  14 ++-
 tests.py                          | 195 +++++++++++++++++++++++-----------
 14 files changed, 555 insertions(+), 315 deletions(-)

diff --git a/Flask_Script.egg-info/PKG-INFO b/Flask_Script.egg-info/PKG-INFO
index ab82ad8..6dd2c95 100644
--- a/Flask_Script.egg-info/PKG-INFO
+++ b/Flask_Script.egg-info/PKG-INFO
@@ -1,11 +1,12 @@
 Metadata-Version: 1.1
 Name: Flask-Script
-Version: 0.6.7
+Version: 2.0.5
 Summary: Scripting support for Flask
-Home-page: http://github.com/techniq/flask-script
-Author: Sean Lynch
-Author-email: techniq35 at gmail.com
+Home-page: http://github.com/smurfix/flask-script
+Author: Matthias Urlichs
+Author-email: matthias at urlichs.de
 License: BSD
+Download-URL: https://github.com/smurfix/flask-script/tarball/v2.0.3
 Description: 
         Flask-Script
         --------------
@@ -20,14 +21,13 @@ Description:
         
         
 Platform: any
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
 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.3
diff --git a/Flask_Script.egg-info/SOURCES.txt b/Flask_Script.egg-info/SOURCES.txt
index 206ff39..2969b97 100644
--- a/Flask_Script.egg-info/SOURCES.txt
+++ b/Flask_Script.egg-info/SOURCES.txt
@@ -1,7 +1,6 @@
 LICENSE
 MANIFEST.in
 README.rst
-setup.cfg
 setup.py
 tests.py
 Flask_Script.egg-info/PKG-INFO
@@ -10,14 +9,12 @@ Flask_Script.egg-info/dependency_links.txt
 Flask_Script.egg-info/not-zip-safe
 Flask_Script.egg-info/requires.txt
 Flask_Script.egg-info/top_level.txt
-docs/.DS_Store
 docs/Makefile
 docs/conf.py
 docs/index.rst
 docs/make.bat
 docs/_static/flask-script.png
 docs/_static/index.html
-docs/_static/index.zip
 docs/_themes/README
 docs/_themes/flask_theme_support.py
 docs/_themes/flask/theme.conf
diff --git a/LICENSE b/LICENSE
index 00199ae..61b4357 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,5 @@
 Copyright (c) 2010 by Dan Jacob.
+Copyright (c) 2014 by Matthias Urlichs.
 
 Some rights reserved.
 
diff --git a/PKG-INFO b/PKG-INFO
index ab82ad8..6dd2c95 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,11 +1,12 @@
 Metadata-Version: 1.1
 Name: Flask-Script
-Version: 0.6.7
+Version: 2.0.5
 Summary: Scripting support for Flask
-Home-page: http://github.com/techniq/flask-script
-Author: Sean Lynch
-Author-email: techniq35 at gmail.com
+Home-page: http://github.com/smurfix/flask-script
+Author: Matthias Urlichs
+Author-email: matthias at urlichs.de
 License: BSD
+Download-URL: https://github.com/smurfix/flask-script/tarball/v2.0.3
 Description: 
         Flask-Script
         --------------
@@ -20,14 +21,13 @@ Description:
         
         
 Platform: any
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: BSD License
 Classifier: Operating System :: OS Independent
 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.3
diff --git a/README.rst b/README.rst
index 0db245e..0fbcd2f 100644
--- a/README.rst
+++ b/README.rst
@@ -1,10 +1,10 @@
 Flask-Script
 ==============
 
-.. image:: https://travis-ci.org/techniq/flask-script.png?branch=master
-        :target: https://travis-ci.org/techniq/flask-script
+.. image:: https://travis-ci.org/smurfix/flask-script.png?branch=v2
+        :target: https://travis-ci.org/smurfix/flask-script
 
-A set of utilities for use with the Flask framework, which provide
+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
@@ -15,4 +15,4 @@ Resources
 ---------
 
 - `Documentation <http://flask-script.readthedocs.org>`_
-- `Issue Tracker <http://github.com/techniq/flask-script/issues>`_
+- `Issue Tracker <http://github.com/smurfix/flask-script/issues>`_
diff --git a/docs/.DS_Store b/docs/.DS_Store
deleted file mode 100644
index 2085b9d..0000000
Binary files a/docs/.DS_Store and /dev/null differ
diff --git a/docs/_static/index.zip b/docs/_static/index.zip
deleted file mode 100644
index 8280eab..0000000
Binary files a/docs/_static/index.zip and /dev/null differ
diff --git a/docs/conf.py b/docs/conf.py
index 9c2c161..f664e60 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -96,7 +96,7 @@ html_theme = 'flask_small'
 
 html_theme_options = {
      'index_logo': 'flask-script.png',
-     'github_fork': 'techniq/flask-script'
+     'github_fork': 'smurfix/flask-script'
 }
 # 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
diff --git a/docs/index.rst b/docs/index.rst
index e5d7f12..3b47db7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -38,7 +38,7 @@ Install with **pip** and **easy_install**::
 
 or download the latest version from version control::
 
-    git clone https://github.com/techniq/flask-script.git
+    git clone https://github.com/smurfix/flask-script.git
     cd flask-script
     python setup.py develop
 
@@ -49,12 +49,12 @@ 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**.
+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
+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 flask.ext.script import Manager
@@ -78,7 +78,7 @@ The next step is to create and add your commands. There are three methods for cr
     * using the ``@command`` decorator
     * using the ``@option`` decorator
 
-To take a very simple example, we want to create a **Hello** command that just prints out "hello world". It
+To take a very simple example, we want to create a ``hello`` command that just prints out "hello world". It
 doesn't take any arguments so is very straightforward::
 
     from flask.ext.script import Command
@@ -111,7 +111,7 @@ To get a list of available commands and their descriptions, just run with no com
 
 To get help text for a particular command::
 
-    python manage.py runserver -h
+    python manage.py runserver -?
 
 This will print usage plus the docstring of the ``Command``.
 
@@ -128,9 +128,9 @@ Commands created this way are run in exactly the same way as those created with
     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::
+As with the ``Command`` class, the docstring you use for the function will appear when you run with the ``-?`` or ``--help`` option::
 
-    python manage.py -h
+    python manage.py -?
     > Just say hello
 
 Finally, the ``@option`` decorator, again belonging to ``Manager`` can be used when you want more sophisticated
@@ -142,6 +142,32 @@ control over your commands::
 
 The ``@option`` decorator is explained in more detail below.
 
+*New in version 2.0*
+
+Help was previously available with ``--help`` and ``-h``. This had a couple
+of less-than-ideal consequences, among them the inability to use ``-h`` as
+a shortcut for ``--host`` or similar options.
+
+*New in version 2.0.2*
+
+If you want to restore the original meaning of ``-h``, set your manager's
+``help_args`` attribute to a list of argument strings you want to be
+considered helpful.
+
+    manager = Manager()
+    manager.help_args = ('-h','-?','--help)
+
+You can override this list in sub-commands and -managers::
+
+    def talker(host='localhost'):
+        pass
+    ccmd = ConnectCmd(talker)
+    ccmd.help_args = ('-?','--help)
+    manager.add_command("connect", ccmd)
+    manager.run()
+
+so that ``manager -h`` prints help, while ``manager connect -h fubar.example.com``
+connects to a remote host.
 
 Adding arguments to commands
 ----------------------------
@@ -204,7 +230,7 @@ Or you can do optional arguments::
 
     @manager.command
     def hello(name="Fred")
-        print hello, name
+        print "hello", name
 
 These can be called like so::
 
@@ -216,12 +242,10 @@ alternatively::
     > python manage.py hello -n Joe
     hello Joe
 
-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.
+The short form ``-n`` is formed from the first letter of the argument, so "name" > "-n". Therefore it's a good idea for your
+optional argument variable names to begin with different letters.
 
-The second issue is that the **-h** switch always runs the help text for that command, so avoid arguments starting with the letter "h".
+*New in version 2.0*
 
 Note also that if your optional argument is a boolean, for example::
 
@@ -301,19 +325,56 @@ Suppose you have this command::
         uppercase = app.config.get('USE_UPPERCASE', False)
         if uppercase:
             name = name.upper()
-        print hello, name
+        print "hello", name
 
 You can now run the following::
 
-    > python manage.py hello joe -c dev.cfg
+    > python manage.py -c dev.cfg hello joe
     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.
+Notice also that the "config" option is **not** passed to the command. In
+fact, this usage
+
+    > python manage.py hello joe -c dev.cfg
+
+will show an error message because the ``-c`` option does not belong to the
+``hello`` command.
+
+You can attach same-named options to different levels; this allows you to
+add an option to your app setup code without checking whether it conflicts with
+a command:
+
+    @manager.option('-n', '--name', dest='name', default='joe')
+    @manager.option('-c', '--clue', dest='clue', default='clue')
+    def hello(name,clue):
+        uppercase = app.config.get('USE_UPPERCASE', False)
+        if uppercase:
+            name = name.upper()
+            clue = clue.upper()
+        print "hello {}, get a {}!".format(name,clue)
+
+    > python manage.py -c dev.cfg hello -c cookie -n frank
+    hello FRANK, get a COOKIE!
+
+Note that the destination variables (command arguments, corresponding to
+``dest`` values) must still be different; this is a limitation of Python's
+argument parser.
 
 In order for manager options to work you must pass a factory function, rather than a Flask instance, to your
-``Manager`` constructor. A simple but complete example is available in `this gist <https://gist.github.com/3531881>`_.
+``Manager`` constructor. A simple but complete example is available in `this gist <https://gist.github.com/smurfix/9307618>`_.
+
+*New in version 2.0*
+
+Before version 2, options and command names could be interspersed freely.
+The author decided to discontinue this practice for a number of reasons;
+the problem with the most impact was that it was not possible to do
+
+    > python manage.py connect -d DEST
+    > python manage.py import -d DIR
+
+as these options collided.
 
 Getting user input
 ------------------
@@ -335,17 +396,20 @@ Getting user input
 
 It then runs like this::
 
-    python manage.py dropdb
-    > Are you sure you want to lose all your data ? [N]
+    > python manage.py dropdb
+    Are you sure you want to lose all your data ? [N]
 
 See the :ref:`api` below for details on the various prompt functions.
 
 Default commands
 ----------------
 
+runserver
++++++++++
+
 **Flask-Script** has a couple of ready commands you can add and customise: ``Server`` and ``Shell``.
 
-The ``Server`` command runs the **Flask** development server. It takes an optional ``port`` argument (default **5000**)::
+The ``Server`` command runs the **Flask** development server.
 
     from flask.ext.script import Server, Manager
     from myapp import create_app
@@ -360,12 +424,32 @@ 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. You can redefine the defaults in the constructor::
+The ``Server`` command has a number of command-line arguments - run ``python manage.py runserver -?`` for details on these. You can redefine the defaults in the constructor::
 
     server = Server(host="0.0.0.0", port=9000)
 
 Needless to say the development server is not intended for production use.
 
+*New in version 2.0.5*
+
+The most common use-case for ``runserver`` is to run a debug server for
+investigating problems. Therefore the default, if it is *not* set in the
+configuration file, is to enable debugging and auto-reloading.
+
+Unfortunately, Flask currently (as of May 2014) defaults to set the DEBUG
+configuration parameter to ``False``. Until this is changed, you can
+safely add ``DEFAULT=None`` to your Flask configuration. Flask-Script's
+``runserver`` will then turn on debugging, but everything else will treat
+it as being turned off.
+
+To prevent misunderstandings -- after all, debug mode is a serious security
+hole --, a warning is printed when Flask-Script treats a ``None`` default
+value as if it were set to ``True``. You can turn on debugging explicitly
+to get rid of this warning.
+
+shell
++++++
+
 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 your Flask application instance::
 
     from flask.ext.script import Shell, Manager
@@ -392,11 +476,11 @@ There is also a ``shell`` decorator which you can use with a context function::
     def make_shell_context():
         return dict(app=app, db=db, models=models)
 
-This enables a **shell** command with the defaults enabled::
+This enables a ``shell`` command with the defaults enabled::
 
     > python manage.py shell
 
-The default commands **shell** and **runserver** are included by default, with the default options for these commands. If you wish to
+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::
 
@@ -408,17 +492,39 @@ A Sub-Manager is an instance of ``Manager`` added as a command to another Manage
 
 To create a submanager::
 
-    sub_manager = Manager()
+    def sub_opts(app, **kwargs):
+        pass
+    sub_manager = Manager(sub_opts)
 
     manager = Manager(self.app)
     manager.add_command("sub_manager", sub_manager)
 
-Restrictions
-    - A sub-manager does not provide an app instance/factory when created, it defers the calls to it's parent Manager's
-    - A sub-manager inhert's the parent Manager's app options (used for the app instance/factory)
-    - A sub-manager does not get default commands added to itself (by default)
-    - A sub-manager must be added the primary/root ``Manager`` instance via ``add_command(sub_manager)``
-    - A sub-manager can be added to another sub-manager as long as the parent sub-manager is added to the primary/root Manager
+If you attach options to the sub_manager, the ``sub_opts`` procedure will
+receive their values. Your application is passed in ``app`` for
+convenience.
+
+If ``sub_opts`` returns a value other than ``None``, this value will replace
+the ``app`` value that's passed on. This way, you can implement a
+sub-manager which replaces the whole app. One use case is to create a
+separate administrative application for improved security::
+
+    def gen_admin(app, **kwargs):
+        from myweb.admin import MyAdminApp
+        ## easiest but possibly incomplete way to copy your settings
+        return MyAdminApp(config=app.config, **kwargs)
+    sub_manager = Manager(gen_admin)
+
+    manager = Manager(MyApp)
+    manager.add_command("admin", sub_manager)
+
+    > python manage.py runserver
+    [ starts your normal server ]
+    > python manage.py admin runserver
+    [ starts an administrative server ]
+
+You can cascade sub-managers, i.e. add one sub-manager to another. 
+
+A sub-manager does not get default commands added to itself (by default)
 
 *New in version 0.5.0.*
 
@@ -486,6 +592,35 @@ The commands will then be available::
       populate  Populate database with default data
       recreate  Recreates database tables (same as issuing 'drop' and then 'create')
 
+Error handling
+--------------
+
+Users do not like to see stack traces, but developers want them for bug reports.
+
+Therefore, ``flask.ext.script.command`` provides an `InvalidCommand` error
+class which is not supposed to print a stack trace when reported.
+
+In your command handler:
+
+	from flask.ext.script.command import InvalidCommand
+
+    [… if some command verification fails …]
+    class MyCommand(Command):
+        def run(self, foo=None,bar=None):
+            if foo and bar:
+	            raise InvalidCommand("Options foo and bar are incompatible")
+
+In your main loop:
+
+    try:
+        MyManager().run()
+    except InvalidCommand as err:
+        print(err, file=sys.stderr)
+        sys.exit(1)
+
+This way, you maintain interoperability if some plug-in code supplies
+Flask-Script hooks you'd like to use, or vice versa.
+
 Accessing local proxies
 -----------------------
 
@@ -521,5 +656,4 @@ API
 .. autofunction:: prompt_choices
 
 .. _Flask: http://flask.pocoo.org
-.. _GitHub: http://github.com/techniq/flask-script
-.. _argparse: http://pypi.python.org/pypi/argparse
+.. _GitHub: http://github.com/smurfix/flask-script
diff --git a/flask_script/__init__.py b/flask_script/__init__.py
index 5a08aea..a80133e 100644
--- a/flask_script/__init__.py
+++ b/flask_script/__init__.py
@@ -5,14 +5,14 @@ import os
 import re
 import sys
 import types
-import inspect
 import warnings
+from gettext import gettext as _
 
 import argparse
 
 from flask import Flask
 
-from ._compat import text_type, iteritems, izip
+from ._compat import iteritems
 from .commands import Group, Option, Command, Server, Shell
 from .cli import prompt, prompt_pass, prompt_bool, prompt_choices
 
@@ -34,6 +34,11 @@ try:
 except ImportError:
     ARGCOMPLETE_IMPORTED = False
 
+def add_help(parser, help_args): 
+    if not help_args:
+        return
+    parser.add_argument(*help_args,
+                        action='help', default=argparse.SUPPRESS, help=_('show this help message and exit'))
 
 class Manager(object):
     """
@@ -59,12 +64,13 @@ class Manager(object):
         python manage.py print
         > hello
 
-    :param app: Flask instance or callable returning a Flask instance.
+    :param app: Flask instance, or callable returning a Flask instance.
     :param with_default_commands: load commands **runserver** and **shell**
                                   by default.
     :param disable_argcomplete: disable automatic loading of argcomplete.
 
     """
+    help_args = ('-?','--help')
 
     def __init__(self, app=None, with_default_commands=None, usage=None,
                  help=None, description=None, disable_argcomplete=False):
@@ -74,54 +80,54 @@ class Manager(object):
         self._commands = dict()
         self._options = list()
 
-        # Primary/root Manager instance adds default commands by default,
-        # Sub-Managers do not
-        if with_default_commands or (app and with_default_commands is None):
-            self.add_default_commands()
-
         self.usage = usage
         self.help = help if help is not None else usage
         self.description = description if description is not None else usage
         self.disable_argcomplete = disable_argcomplete
+        self.with_default_commands = with_default_commands
 
         self.parent = None
 
     def add_default_commands(self):
         """
-        Adds the shell and runserver default commands. To override these
+        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())
+        if "shell" not in self._commands:
+            self.add_command("shell", Shell())
+        if "runserver" not in self._commands:
+            self.add_command("runserver", Server())
 
     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.
+        Adds a global 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.
+        function rather than a Flask instance. Otherwise any options you set
+        will be ignored.
 
         The arguments are then passed to your function, e.g.::
 
-            def create_app(config=None):
+            def create_my_app(config=None):
                 app = Flask(__name__)
                 if config:
                     app.config.from_pyfile(config)
 
                 return app
 
-            manager = Manager(create_app)
+            manager = Manager(create_my_app)
             manager.add_option("-c", "--config", dest="config", required=False)
+            @manager.command
+            def mycommand(app):
+                app.do_something()
 
-        and are evoked like this::
+        and are invoked like this::
 
             > python manage.py -c dev.cfg mycommand
 
-        Any manager options passed in the command line will not be passed to
+        Any manager options passed on the command line will not be passed to
         the command.
 
         Arguments for this function are the same as for the Option class.
@@ -129,33 +135,49 @@ class Manager(object):
 
         self._options.append(Option(*args, **kwargs))
 
-    def create_app(self, **kwargs):
-        if self.parent:
-            # Sub-manager, defer to parent Manager
-            return self.parent.create_app(**kwargs)
+    def __call__(self, app=None, **kwargs):
+        """
+        This procedure is called with the App instance (if this is a
+        sub-Manager) and any options. 
 
-        if isinstance(self.app, Flask):
-            return self.app
+        If your sub-Manager does not override this, any values for options will get lost.
+        """
+        if app is None:
+            app = self.app
+            if app is None:
+                raise Exception("There is no app here. This is unlikely to work.")
+
+        if isinstance(app, Flask):
+            if kwargs:
+                import warnings
+                warnings.warn("Options will be ignored.")
+            return app
+
+        app = app(**kwargs)
+        self.app = app
+        return app
 
-        return self.app(**kwargs)
+    def create_app(self, *args, **kwargs):
+        warnings.warn("create_app() is deprecated; use __call__().", warnings.DeprecationWarning)
+        return self(*args,**kwargs)
 
-    def create_parser(self, prog, parents=None):
+    def create_parser(self, prog, func_stack=(), parent=None):
         """
         Creates an ArgumentParser instance from options returned
-        by get_options(), and a subparser for the given command.
+        by get_options(), and subparser for the given commands.
         """
         prog = os.path.basename(prog)
+        func_stack=func_stack+(self,)
 
         options_parser = argparse.ArgumentParser(add_help=False)
         for option in self.get_options():
             options_parser.add_argument(*option.args, **option.kwargs)
 
-        # parser_parents = parents if parents else [option_parser]
-        # parser_parents = [options_parser]
-
         parser = argparse.ArgumentParser(prog=prog, usage=self.usage,
                                          description=self.description,
-                                         parents=[options_parser])
+                                         parents=[options_parser],
+                                         add_help=False)
+        add_help(parser, self.help_args)
 
         self._patch_argparser(parser)
 
@@ -163,29 +185,28 @@ class Manager(object):
 
         for name, command in self._commands.items():
             usage = getattr(command, 'usage', None)
-            help = getattr(command, 'help', command.__doc__)
-            description = getattr(command, 'description', command.__doc__)
+            help = getattr(command, 'help', None)
+            if help is None: help = command.__doc__
+            description = getattr(command, 'description', None)
+            if description is None: description = command.__doc__
 
-            # Only pass `parents` argument for commands that support it
-            try:
-                command_parser = command.create_parser(name, parents=[options_parser])
-            except TypeError:
-                warnings.warn("create_parser for {0} command should accept a `parents` argument".format(name), DeprecationWarning)
-                command_parser = command.create_parser(name)
+            command_parser = command.create_parser(name, func_stack=func_stack, parent=self)
 
             subparser = subparsers.add_parser(name, usage=usage, help=help,
                                               description=description,
-                                              parents=[command_parser], add_help=False)
+                                              parents=[command_parser],
+                                              add_help=False)
 
             if isinstance(command, Manager):
                 self._patch_argparser(subparser)
 
         ## enable autocomplete only for parent parser when argcomplete is
         ## imported and it is NOT disabled in constructor
-        if parents is None and ARGCOMPLETE_IMPORTED \
+        if parent is None and ARGCOMPLETE_IMPORTED \
                 and not self.disable_argcomplete:
             argcomplete.autocomplete(parser, always_complete_options=True)
 
+        self.parser = parser
         return parser
 
     # def foo(self, app, *args, **kwargs):
@@ -207,9 +228,6 @@ class Manager(object):
         parser._parse_known_args = types.MethodType(_parse_known_args, parser)
 
     def get_options(self):
-        if self.parent:
-            return self.parent._options
-
         return self._options
 
     def add_command(self, *args, **kwargs):
@@ -264,44 +282,7 @@ class Manager(object):
 
         """
 
-        args, varargs, keywords, defaults = inspect.getargspec(func)
-
-        options = []
-
-        # first arg is always "app" : ignore
-
-        defaults = defaults or []
-        kwargs = dict(izip(*[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,
-                                          type=text_type,
-                                          required=False,
-                                          default=default))
-
-            else:
-                options.append(Option(arg, type=text_type))
-
-        command = Command()
-        command.run = func
-        command.__doc__ = func.__doc__
-        command.option_list = options
-
+        command = Command(func)
         self.add_command(func.__name__, command)
 
         return func
@@ -357,49 +338,57 @@ class Manager(object):
 
         return func
 
-    def handle(self, prog, args=None):
+    def set_defaults(self):
+        if self.with_default_commands is None:
+            self.with_default_commands = self.parent is None
+        if self.with_default_commands:
+            self.add_default_commands()
+        self.with_default_commands = False
 
+    def handle(self, prog, args=None):
+        self.set_defaults()
         app_parser = self.create_parser(prog)
-
+        
         args = list(args or [])
         app_namespace, remaining_args = app_parser.parse_known_args(args)
 
         # get the handle function and remove it from parsed options
         kwargs = app_namespace.__dict__
-        handle = kwargs.pop('func_handle', None)
-        if not handle:
+        func_stack = kwargs.pop('func_stack', None)
+        if not func_stack:
             app_parser.error('too few arguments')
 
-        # get only safe config options
-        app_config_keys = [action.dest for action in app_parser._actions
-                           if action.__class__ in safe_actions]
+        last_func = func_stack[-1]
+        if remaining_args and not getattr(last_func, 'capture_all_args', False):
+            app_parser.error('too many arguments')
 
-        # pass only safe app config keys
-        app_config = dict((k, v) for k, v in iteritems(kwargs)
-                          if k in app_config_keys)
+        args = []
+        for handle in func_stack:
 
-        # remove application config keys from handle kwargs
-        kwargs = dict((k, v) for k, v in iteritems(kwargs)
-                      if k not in app_config_keys)
+            # get only safe config options
+            config_keys = [action.dest for action in handle.parser._actions
+                               if handle is last_func or action.__class__ in safe_actions]
 
-        # get command from bound handle function (py2.7+)
-        command = handle.__self__
-        if getattr(command, 'capture_all_args', False):
-            positional_args = [remaining_args]
-        else:
-            if len(remaining_args):
-                # raise correct exception
-                # FIXME maybe change capture_all_args flag
-                app_parser.parse_args(args)
-                # sys.exit(2)
-                pass
-            positional_args = []
-
-        app = self.create_app(**app_config)
-        # for convience usage in a command
-        self.app = app
+            # pass only safe app config keys
+            config = dict((k, v) for k, v in iteritems(kwargs)
+                          if k in config_keys)
+
+            # remove application config keys from handle kwargs
+            kwargs = dict((k, v) for k, v in iteritems(kwargs)
+                          if k not in config_keys)
+
+            if handle is last_func and getattr(last_func, 'capture_all_args', False):
+                args.append(remaining_args)
+            try:
+                res = handle(*args, **config)
+            except TypeError as err:
+                err.args = ("{}: {}".format(handle,str(err)),)
+                raise
+
+            args = [res]
 
-        return handle(app, *positional_args, **kwargs)
+        assert not kwargs
+        return res
 
     def run(self, commands=None, default_command=None):
         """
diff --git a/flask_script/commands.py b/flask_script/commands.py
index 8cdc538..62477bf 100644
--- a/flask_script/commands.py
+++ b/flask_script/commands.py
@@ -1,22 +1,34 @@
 # -*- coding: utf-8 -*-
-from __future__ import absolute_import
+from __future__ import absolute_import,print_function
 
 import os
+import sys
 import code
 import warnings
 import string
+import inspect
 
 import argparse
 
 from flask import _request_ctx_stack
 
 from .cli import prompt, prompt_pass, prompt_bool, prompt_choices
+from ._compat import izip, text_type
 
 
 class InvalidCommand(Exception):
+    """\
+        This is a generic error for "bad" commands.
+        It is not used in Flask-Script itself, but you should throw
+        this error (or one derived from it) in your command handlers,
+        and your main code should display this error's message without
+        a stack trace.
+
+        This way, we maintain interoperability if some other plug-in code
+        supplies Flask-Script hooks.
+        """
     pass
 
-
 class Group(object):
     """
     Stores argument groups and mutually exclusive groups for
@@ -90,9 +102,57 @@ class Option(object):
 class Command(object):
     """
     Base class for creating commands.
+
+    :param func:  Initialize this command by introspecting the function.
     """
 
-    option_list = []
+    option_list = ()
+    help_args = None
+
+    def __init__(self, func=None):
+        if func is None:
+            if not self.option_list:
+                self.option_list = []
+            return
+
+        args, varargs, keywords, defaults = inspect.getargspec(func)
+        if inspect.ismethod(func):
+            args = args[1:]
+            
+        options = []
+        
+        # first arg is always "app" : ignore
+        
+        defaults = defaults or []
+        kwargs = dict(izip(*[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,
+                                          type=text_type,
+                                          required=False,
+                                          default=default))
+                                          
+            else:
+                options.append(Option(arg, type=text_type))
+                
+        self.run = func
+        self.__doc__ = func.__doc__
+        self.option_list = options
 
     @property
     def description(self):
@@ -113,8 +173,17 @@ class Command(object):
         return self.option_list
 
     def create_parser(self, *args, **kwargs):
-
-        parser = argparse.ArgumentParser(*args, **kwargs)
+        func_stack = kwargs.pop('func_stack',())
+        parent = kwargs.pop('parent',None)
+        parser = argparse.ArgumentParser(*args, add_help=False, **kwargs)
+        help_args = self.help_args
+        while help_args is None and parent is not None:
+            help_args = parent.help_args
+            parent = getattr(parent,'parent',None)
+
+        if help_args:
+            from flask_script import add_help
+            add_help(parser,help_args)
... 773 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/flask-script.git



More information about the Python-modules-commits mailing list