Commits

danjac  committed d51c0a4 Merge

merged app-removal

  • Participants
  • Parent commits d837663, 02a1003

Comments (0)

Files changed (5)

File docs/index.rst

     manager = Manager(app)
     
     @manager.command
-    def hello(app):
+    def hello():
         print "hello"
 
     if __name__ == "__main__":
     class Hello(Command):
         "prints hello world"
 
-        def run(self, app):
+        def run(self):
             print "hello world"
 
 Now the command needs to be added to our ``Manager`` instance, like the one created above::
 
     manager.run({'hello' : Hello()})
 
-The ``Command`` class must define a ``run`` method. The first argument to your ``run`` , other than ``self``, 
-is always ``app``: this is the Flask application instance that is passed directly to the ``Manager``; if you 
-pass an app factory, the ``Manager`` will call this and pass the result to your ``Command``. Additional arguments
+The ``Command`` class must define a ``run`` method. The positional and optional arguments
 depend on the command-line arguments you pass to the ``Command`` (see below).
 
 To get a list of available commands and their descriptions, just run with no command::
 the ``@command`` decorator, which belongs to the ``Manager`` instance:: 
 
     @manager.command
-    def hello(app):
+    def hello():
         "Just say hello"
         print "hello"
 
 
 The ``@option`` decorator is explained in more detail 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
 ----------------------------
             Option('--name', '-n', dest='name'),
         )
 
-        def run(self, app, name):
+        def run(self, name):
             print "hello %s" % name
 
 Positional and optional arguments are stored as ``Option`` instances - see the :ref:`api` below for details.
                 Option('-n', '--name', dest='name', default=self.default_name),
             ]
 
-        def run(self, app, name):
+        def run(self, name):
             print "hello",  name
 
 If you are using the ``@command`` decorator, it's much easier - the options are extracted automatically from your function arguments. This is an example of a positional argument::
 
     @manager.command
-    def hello(app, name):
+    def hello(name):
         print "hello", name
 
 You then invoke this on the command line like so::
 Or you can do optional arguments::
 
     @manager.command
-    def hello(app, name="Fred")
+    def hello(name="Fred")
         print hello, name
 
 These can be called like so::
 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 first argument, "app", is ignored, 
-so don't worry about "a" being taken).
+optional argument variable names 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".
 
 Note also that if your optional argument is a boolean, for example::
 
     @manage.command
-    def verify(app, verified=False):
+    def verify(verified=False):
         """
         Checks if verified
         """
 The ``@command`` decorator is fine for simple operations, but often you need the flexibility. For more sophisticated options it's better to use the ``@option`` decorator::
 
     @manager.option('-n', '--name', dest='name', default='joe')
-    def hello(app, name):
+    def hello(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):
+    def hello(name, url):
         if url is None:
             print "hello", name
         else:
 Suppose you have this command::
     
     @manager.command
-    def hello(app, name):
+    def hello(name):
         uppercase = app.config.get('USE_UPPERCASE', False)
         if uppercase:
             name = name.upper()
     manager = Manager(app)
         
     @manager.command
-    def dropdb(app):
+    def dropdb():
         if prompt_bool(
             "Are you sure you want to lose all your data"):
             db.drop_all()
 
 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``. As with commands, it always takes the ``app`` as the first argument. By default, this is just a dict returning the ``app`` instance::
+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 import app
 
     from flaskext.script import Shell, Manager
     
     from myapp import models
     from myapp.models import db
 
-    def _make_context(app):
-        return dict(app=app, db=db, models=models)
+    def _make_context():
+        return dict(app=app, app, db=db, models=models)
 
     manager = Manager(create_app)
     manager.add_command("shell", Shell(make_context=_make_context))
 
     shell = Shell(use_ipython=False)
 
-There is also a ``@shell`` decorator which you can use with a context function::
+There is also a ``shell`` decorator which you can use with a context function::
 
-    @shell
-    def make_shell_context(app):
+    @manager.shell
+    def make_shell_context():
         return dict(app=app, db=db, models=models)
 
 This enables a **shell** command with the defaults enabled::

File examples/manage.py

 import pprint
 
-from flask import Flask, Response
-from flaskext.script import Manager, Command, Option, Shell, Server
+from flask import Flask, current_app
+from flaskext.script import Manager, prompt_choices
 
 def create_app(config=None):
     app = Flask(__name__)
 manager = Manager(create_app)
 
 @manager.command
-def dumpconfig(app):
+def dumpconfig():
     "Dumps config"
-    pprint.pprint(app.config)
+    pprint.pprint(current_app.config)
 
 @manager.command
-def output(app, name):
+def output(name):
     "print something"
     print name
 
 @manager.command
-def outputplus(app, name, url=None):
+def outputplus(name, url=None):
     "print name and url"
     print name, url
 
+@manager.command
+def getrolesimple():
+
+    choices = ("member", "moderator", "admin")
+
+    role = prompt_choices("role", choices=choices, default="member")
+    print "ROLE:", role
+
+@manager.command
+def getrole():
+
+    choices = (
+        (1, "member"),
+        (2, "moderator"),
+        (3, "admin"),
+    )
+
+    role = prompt_choices("role", choices=choices, resolve=int, default=1)
+    print "ROLE:", role
+
 @manager.option('-n', '--name', dest='name', help="your name")
 @manager.option('-u', '--url', dest='url', help="your url")
-def optional(app, name, url):
+def optional(name, url):
     "print name and url"
     print name, url
 

File flaskext/script.py

 # -*- 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
+from flask import Flask, _request_ctx_stack
 
 __all__ = ["Command", "Shell", "Server", "Manager", "Option",
            "prompt", "prompt_pass", "prompt_bool", "prompt_choices"]
     no_choices = no_choices or ('n', 'no', '0', 'off', 'false', 'f')
     
     while True:
-        rv = prompt(name + '?', default and 'Y' or 'N')
+        rv = prompt(name + '?', default and yes_choices[0] or no_choices[0])
         if not rv:
             return default
         if rv.lower() in yes_choices:
             return False
 
 
-def prompt_choices(name, choices, default=None):
+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
+    :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)
 
-    if default is None:
-        default = choices[0]
     while True:
-        rv = prompt(name + '? - (%s)' % ', '.join(choices), default)
-        rv = rv.lower()
+        rv = prompt(name + '? - (%s)' % ', '.join(options), default)
         if not rv:
             return default
-        if rv in choices:
-            if rv == 'none':
-                return None
-            else:
-                return rv
+        rv = resolve(rv)
+        if rv in no_choice:
+            return None
+        if rv in _choices:
+            return rv
 
 
 class Option(object):
         
         return parser
 
-    def run(self, app):
+    def run(self):
 
         """
         Runs a command. This must be implemented by the subclass. The first
         self.use_ipython = use_ipython
 
         if make_context is None:
-            make_context = lambda app: dict(app=app)
+            make_context = lambda: dict(app=_request_ctx_stack.top.app)
 
         self.make_context = make_context
     
                        dest='no_ipython',
                        default=not(self.use_ipython)),)
 
-    def get_context(self, app):
+    def get_context(self):
         
         """
         Returns a dict of context variables added to the shell namespace.
         """
 
-        return self.make_context(app)
+        return self.make_context()
 
-    def run(self, app, no_ipython):
+    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(app)
+        context = self.get_context()
         if not no_ipython:
             try:
                 import IPython
                        dest='use_reloader',
                        default=self.use_reloader))
 
-    def run(self, app, host, port, use_debugger, 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,
 
         # first arg is always "app" : ignore
 
-        args = args[1:]
         defaults = defaults or []
         kwargs = dict(zip(*[reversed(l) for l in (args, defaults)]))
 
         app = self.create_app(**app_namespace.__dict__)
 
         with app.test_request_context():
-            command.run(app, **command_namespace.__dict__)
-        
+            command.run(**command_namespace.__dict__)
+
     def run(self, commands=None):
         
         """
 
 * `documentation <http://packages.python.org/Flask-Script>`_
 * `development version
-  <http://bitbucket.org/danjac/flask-Script/get/tip.gz#egg=flask-script>`_
+  <http://bitbucket.org/danjac/flask-Script/get/tip.gz#egg=Flask-Script-dev>`_
 
 
 """
 
 setup(
     name='Flask-Script',
-    version='0.2',
+    version='0.3',
     url='http://bitbucket.org/danjac/flask-script',
     license='BSD',
     author='Dan Jacob',
     long_description=__doc__,
     packages=['flaskext'],
     namespace_packages=['flaskext'],
+    test_suite='nose.collector',
     zip_safe=False,
     platforms='any',
     install_requires=[
         'Flask',
         'argparse',
     ],
+    tests_require=[
+        'nose',
+    ],
     classifiers=[
         'Development Status :: 4 - Beta',
         'Environment :: Web Environment',
 class SimpleCommand(Command):
     "simple command"
 
-    def run(self, app):
+    def run(self):
         print "OK"
 
 
         Option("name"),
     )
 
-    def run(self, app, name):
+    def run(self, name):
         print name
 
 
                dest="name"),
     )
 
-    def run(self, app, name):
+    def run(self, name):
         print name
 
 
                    default=self.default_name),
             )
 
-    def run(self, app, name):
+    def run(self, name):
         print name
 
 
         manager = Manager(self.app)
         
         @manager.command
-        def hello(app):
+        def hello():
             print "hello"
 
         assert 'hello' in manager._commands
         manager = Manager(self.app)
         
         @manager.command
-        def hello(app, name):
+        def hello(name):
             print "hello", name
         
 
         manager = Manager(self.app)
         
         @manager.command
-        def hello(app, name='fred'):
+        def hello(name='fred'):
             "Prints your name"
             print "hello", name
 
         manager = Manager(self.app)
         
         @manager.command
-        def verify(app, verified=False):
+        def verify(verified=False):
             "Checks if verified"
             print "VERIFIED ?", "YES" if verified else "NO"
 
         manager = Manager(self.app)
         
         @manager.command
-        def hello(app, name, url=None):
+        def hello(name, url=None):
             if url:
                 print "hello", name, "from", url
             else:
         manager = Manager(self.app)
         
         @manager.option('-n', '--name', dest='name', help='Your name')
-        def hello(app, name):
+        def hello(name):
             print "hello", name
 
         assert 'hello' in manager._commands
 
         @manager.option('-n', '--name', dest='name', help='Your name')
         @manager.option('-u', '--url', dest='url', help='Your URL')
-        def hello_again(app, name, url=None):
+        def hello_again(name, url=None):
             if url:
                 print "hello", name, "from", url
             else: