deprecate passing script_info to factory

This commit is contained in:
David Lord 2020-04-07 15:54:36 -07:00
parent 7e3b8abf99
commit fcac7f11cf
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
5 changed files with 45 additions and 38 deletions

View File

@ -9,6 +9,9 @@ Unreleased
- JSON support no longer uses simplejson. To use another JSON module,
override ``app.json_encoder`` and ``json_decoder``. :issue:`3555`
- The ``encoding`` option to JSON functions is deprecated. :pr:`3562`
- Passing ``script_info`` to app factory functions is deprecated. This
was not portable outside the ``flask`` command. Use
``click.get_current_context().obj`` if it's needed. :issue:`3552`
- Add :meth:`sessions.SessionInterface.get_cookie_name` to allow
setting the session cookie name dynamically. :pr:`3369`
- Add :meth:`Config.from_file` to load config using arbitrary file

View File

@ -75,13 +75,9 @@ Within the given import, the command looks for an application instance named
found, the command looks for a factory function named ``create_app`` or
``make_app`` that returns an instance.
When calling an application factory, if the factory takes an argument named
``script_info``, then the :class:`~cli.ScriptInfo` instance is passed as a
keyword argument. If the application factory takes only one argument and no
parentheses follow the factory name, the :class:`~cli.ScriptInfo` instance
is passed as a positional argument. If parentheses follow the factory name,
their contents are parsed as Python literals and passes as arguments to the
function. This means that strings must still be in quotes.
If parentheses follow the factory name, their contents are parsed as
Python literals and passed as arguments to the function. This means that
strings must still be in quotes.
Run the Development Server

View File

@ -5,6 +5,7 @@ import platform
import re
import sys
import traceback
import warnings
from functools import update_wrapper
from operator import attrgetter
from threading import Lock
@ -91,14 +92,22 @@ def call_factory(script_info, app_factory, arguments=()):
the app_factory depending on that and the arguments provided.
"""
args_spec = inspect.getfullargspec(app_factory)
arg_names = args_spec.args
arg_defaults = args_spec.defaults
if "script_info" in arg_names:
if "script_info" in args_spec.args:
warnings.warn(
"The 'script_info' argument is deprecated and will not be"
" passed to the app factory function in 2.1.",
DeprecationWarning,
)
return app_factory(*arguments, script_info=script_info)
elif arguments:
return app_factory(*arguments)
elif not arguments and len(arg_names) == 1 and arg_defaults is None:
elif not arguments and len(args_spec.args) == 1 and args_spec.defaults is None:
warnings.warn(
"Script info is deprecated and will not be passed as the"
" first argument to the app factory function in 2.1.",
DeprecationWarning,
)
return app_factory(script_info)
return app_factory()
@ -131,10 +140,8 @@ def _called_with_wrong_args(factory):
def find_app_by_string(script_info, module, app_name):
"""Checks if the given string is a variable name or a function. If it is a
function, it checks for specified arguments and whether it takes a
``script_info`` argument and calls the function with the appropriate
arguments.
"""Check if the given string is a variable name or a function. Call
a function to get the app instance, or return the variable directly.
"""
from . import Flask

View File

@ -9,9 +9,5 @@ def create_app2(foo, bar):
return Flask("_".join(["app2", foo, bar]))
def create_app3(foo, script_info):
return Flask("_".join(["app3", foo, script_info.data["test"]]))
def no_app():
pass

View File

@ -67,32 +67,40 @@ def test_find_best_app(test_apps):
def create_app():
return Flask("appname")
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == "appname"
app = find_best_app(script_info, Module)
assert isinstance(app, Flask)
assert app.name == "appname"
class Module:
@staticmethod
def create_app(foo):
return Flask("appname")
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == "appname"
with pytest.deprecated_call(match="Script info"):
app = find_best_app(script_info, Module)
assert isinstance(app, Flask)
assert app.name == "appname"
class Module:
@staticmethod
def create_app(foo=None, script_info=None):
return Flask("appname")
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == "appname"
with pytest.deprecated_call(match="script_info"):
app = find_best_app(script_info, Module)
assert isinstance(app, Flask)
assert app.name == "appname"
class Module:
@staticmethod
def make_app():
return Flask("appname")
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == "appname"
app = find_best_app(script_info, Module)
assert isinstance(app, Flask)
assert app.name == "appname"
class Module:
myapp = Flask("appname1")
@ -199,15 +207,12 @@ def test_prepare_import(request, value, path, result):
("cliapp.factory", 'create_app2("foo", "bar")', "app2_foo_bar"),
# trailing comma space
("cliapp.factory", 'create_app2("foo", "bar", )', "app2_foo_bar"),
# takes script_info
("cliapp.factory", 'create_app3("foo")', "app3_foo_spam"),
# strip whitespace
("cliapp.factory", " create_app () ", "app"),
),
)
def test_locate_app(test_apps, iname, aname, result):
info = ScriptInfo()
info.data["test"] = "spam"
assert locate_app(info, iname, aname).name == result
@ -286,7 +291,7 @@ def test_scriptinfo(test_apps, monkeypatch):
assert app.name == "testapp"
assert obj.load_app() is app
def create_app(info):
def create_app():
return Flask("createapp")
obj = ScriptInfo(create_app=create_app)
@ -324,7 +329,7 @@ def test_with_appcontext(runner):
def testcmd():
click.echo(current_app.name)
obj = ScriptInfo(create_app=lambda info: Flask("testapp"))
obj = ScriptInfo(create_app=lambda: Flask("testapp"))
result = runner.invoke(testcmd, obj=obj)
assert result.exit_code == 0
@ -350,7 +355,7 @@ def test_appgroup(runner):
def test2():
click.echo(current_app.name)
obj = ScriptInfo(create_app=lambda info: Flask("testappgroup"))
obj = ScriptInfo(create_app=lambda: Flask("testappgroup"))
result = runner.invoke(cli, ["test"], obj=obj)
assert result.exit_code == 0
@ -364,7 +369,7 @@ def test_appgroup(runner):
def test_flaskgroup(runner):
"""Test FlaskGroup."""
def create_app(info):
def create_app():
return Flask("flaskgroup")
@click.group(cls=FlaskGroup, create_app=create_app)
@ -384,7 +389,7 @@ def test_flaskgroup(runner):
def test_flaskgroup_debug(runner, set_debug_flag):
"""Test FlaskGroup debug flag behavior."""
def create_app(info):
def create_app():
app = Flask("flaskgroup")
app.debug = True
return app
@ -405,7 +410,7 @@ def test_flaskgroup_debug(runner, set_debug_flag):
def test_print_exceptions(runner):
"""Print the stacktrace if the CLI."""
def create_app(info):
def create_app():
raise Exception("oh no")
return Flask("flaskgroup")
@ -422,7 +427,7 @@ def test_print_exceptions(runner):
class TestRoutes:
@pytest.fixture
def invoke(self, runner):
def create_app(info):
def create_app():
app = Flask(__name__)
app.testing = True
@ -441,7 +446,7 @@ class TestRoutes:
@pytest.fixture
def invoke_no_routes(self, runner):
def create_app(info):
def create_app():
app = Flask(__name__, static_folder=None)
app.testing = True