Skip to content

Commit 4d09a6a

Browse files
committed
Cleanup create_app and parent handling
also add a bit of documentation
1 parent 8105672 commit 4d09a6a

File tree

2 files changed

+45
-38
lines changed

2 files changed

+45
-38
lines changed

flask_script/__init__.py

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def run(self):
6262
python manage.py print
6363
> hello
6464
65-
:param app: Flask instance or callable returning a Flask instance.
65+
:param app: Flask instance, or callable returning a Flask instance.
6666
:param with_default_commands: load commands **runserver** and **shell**
6767
by default.
6868
:param disable_argcomplete: disable automatic loading of argcomplete.
@@ -87,7 +87,7 @@ def __init__(self, app=None, with_default_commands=None, usage=None,
8787

8888
def add_default_commands(self):
8989
"""
90-
Adds the shell and runserver default commands. To override these
90+
Adds the shell and runserver default commands. To override these,
9191
simply add your own equivalents using add_command or decorators.
9292
"""
9393

@@ -98,62 +98,70 @@ def add_default_commands(self):
9898

9999
def add_option(self, *args, **kwargs):
100100
"""
101-
Adds an application-wide option. This is useful if you want to set
102-
variables applying to the application setup, rather than individual
103-
commands.
101+
Adds a global option. This is useful if you want to set variables
102+
applying to the application setup, rather than individual commands.
104103
105104
For this to work, the manager must be initialized with a factory
106-
function rather than an instance. Otherwise any options you set will
107-
be ignored.
105+
function rather than a Flask instance. Otherwise any options you set
106+
will be ignored.
108107
109108
The arguments are then passed to your function, e.g.::
110109
111-
def create_app(config=None):
110+
def create_my_app(config=None):
112111
app = Flask(__name__)
113112
if config:
114113
app.config.from_pyfile(config)
115114
116115
return app
117116
118-
manager = Manager(create_app)
117+
manager = Manager(create_my_app)
119118
manager.add_option("-c", "--config", dest="config", required=False)
119+
@manager.command
120+
def mycommand(app):
121+
app.do_something()
120122
121-
and are evoked like this::
123+
and are invoked like this::
122124
123125
> python manage.py -c dev.cfg mycommand
124126
125-
Any manager options passed in the command line will not be passed to
127+
Any manager options passed on the command line will not be passed to
126128
the command.
127129
128130
Arguments for this function are the same as for the Option class.
129131
"""
130132

131133
self._options.append(Option(*args, **kwargs))
132134

133-
def create_app(self, app=None, **kwargs):
134-
if self.app is None:
135-
# defer to parent Manager
136-
return self.parent.create_app(**kwargs)
137-
138-
if isinstance(self.app, Flask):
139-
return self.app
140-
141-
return self.app(**kwargs) or app
142-
143-
def __call__(self, app=None, *args, **kwargs):
135+
def __call__(self, app=None, **kwargs):
144136
"""
145-
Call self.app()
137+
This procedure is called with the App instance (if this is a
138+
sub-Manager) and any options.
139+
140+
If your sub-Manager does not override this, any values for options will get lost.
146141
"""
147-
res = self.create_app(app, *args, **kwargs)
148-
if res is None:
149-
res = app
150-
return res
142+
if app is None:
143+
app = self.app
144+
if app is None:
145+
raise Exception("There is no app here. This is unlikely to work.")
146+
147+
if isinstance(app, Flask):
148+
if kwargs:
149+
import warnings
150+
warnings.warn("Options will be ignored.")
151+
return app
152+
153+
app = app(**kwargs)
154+
self.app = app
155+
return app
151156

157+
def create_app(self, *args, **kwargs):
158+
warnings.warn("create_app() is deprecated; use __call__().", warnings.DeprecationWarning)
159+
return self(*args,**kwargs)
152160

153-
def create_parser(self, prog, func_stack=(), parents=None):
161+
def create_parser(self, prog, func_stack=(), parent=None):
154162
"""
155163
Creates an ArgumentParser instance from options returned
156-
by get_options(), and a subparser for the given command.
164+
by get_options(), and subparser for the given commands.
157165
"""
158166
prog = os.path.basename(prog)
159167
func_stack=func_stack+(self,)
@@ -162,9 +170,6 @@ def create_parser(self, prog, func_stack=(), parents=None):
162170
for option in self.get_options():
163171
options_parser.add_argument(*option.args, **option.kwargs)
164172

165-
# parser_parents = parents if parents else [option_parser]
166-
# parser_parents = [options_parser]
167-
168173
parser = argparse.ArgumentParser(prog=prog, usage=self.usage,
169174
description=self.description,
170175
parents=[options_parser],
@@ -182,7 +187,7 @@ def create_parser(self, prog, func_stack=(), parents=None):
182187
description = getattr(command, 'description', None)
183188
if description is None: description = command.__doc__
184189

185-
command_parser = command.create_parser(name, func_stack=func_stack)
190+
command_parser = command.create_parser(name, func_stack=func_stack, parent=self)
186191

187192
subparser = subparsers.add_parser(name, usage=usage, help=help,
188193
description=description,
@@ -194,7 +199,7 @@ def create_parser(self, prog, func_stack=(), parents=None):
194199

195200
## enable autocomplete only for parent parser when argcomplete is
196201
## imported and it is NOT disabled in constructor
197-
if parents is None and ARGCOMPLETE_IMPORTED \
202+
if parent is None and ARGCOMPLETE_IMPORTED \
198203
and not self.disable_argcomplete:
199204
argcomplete.autocomplete(parser, always_complete_options=True)
200205

@@ -355,8 +360,6 @@ def handle(self, prog, args=None):
355360
app_parser.error('too many arguments')
356361

357362
args = []
358-
if self.app is not None:
359-
args.append(self.app)
360363
for handle in func_stack:
361364

362365
# get only safe config options

flask_script/commands.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ def get_options(self):
165165
def create_parser(self, *args, **kwargs):
166166

167167
func_stack = kwargs.pop('func_stack',())
168+
parent = kwargs.pop('parent',None)
168169
parser = argparse.ArgumentParser(*args, add_help=False, **kwargs)
169170
if self.add_help:
170171
from flask_script import add_help
@@ -189,6 +190,7 @@ def create_parser(self, *args, **kwargs):
189190
parser.set_defaults(func_stack=func_stack+(self,))
190191

191192
self.parser = parser
193+
self.parent = parent
192194
return parser
193195

194196
def __call__(self, app=None, *args, **kwargs):
@@ -243,11 +245,13 @@ def get_options(self):
243245
Option('--no-ipython',
244246
action="store_true",
245247
dest='no_ipython',
246-
default=not(self.use_ipython)),
248+
default=not(self.use_ipython),
249+
help="Do not use the BPython shell"),
247250
Option('--no-bpython',
248251
action="store_true",
249252
dest='no_bpython',
250-
default=not(self.use_bpython))
253+
default=not(self.use_bpython),
254+
help="Do not use the IPython shell"),
251255
)
252256

253257
def get_context(self):

0 commit comments

Comments
 (0)