Browse Source

Merge remote-tracking branch 'pallets/master' into 2313-refactor-gevent-tests-into-class

pull/2324/head
Rene A. Zelaya 8 years ago
parent
commit
f40617029a
  1. 5
      CHANGES
  2. 9
      docs/quickstart.rst
  3. 2
      flask/_compat.py
  4. 28
      flask/cli.py
  5. 2
      setup.py
  6. 62
      tests/test_cli.py
  7. 8
      tox.ini

5
CHANGES

@ -42,6 +42,10 @@ Major release, unreleased
(`#2282`_) (`#2282`_)
- Auto-detect zero-argument app factory called ``create_app`` or ``make_app`` - Auto-detect zero-argument app factory called ``create_app`` or ``make_app``
from ``FLASK_APP``. (`#2297`_) from ``FLASK_APP``. (`#2297`_)
- Factory functions are not required to take a ``script_info`` parameter to
work with the ``flask`` command. If they take a single parameter or a
parameter named ``script_info``, the ``ScriptInfo`` object will be passed.
(`#2319`_)
.. _#1489: https://github.com/pallets/flask/pull/1489 .. _#1489: https://github.com/pallets/flask/pull/1489
.. _#1898: https://github.com/pallets/flask/pull/1898 .. _#1898: https://github.com/pallets/flask/pull/1898
@ -53,6 +57,7 @@ Major release, unreleased
.. _#2259: https://github.com/pallets/flask/pull/2259 .. _#2259: https://github.com/pallets/flask/pull/2259
.. _#2282: https://github.com/pallets/flask/pull/2282 .. _#2282: https://github.com/pallets/flask/pull/2282
.. _#2297: https://github.com/pallets/flask/pull/2297 .. _#2297: https://github.com/pallets/flask/pull/2297
.. _#2319: https://github.com/pallets/flask/pull/2319
Version 0.12.2 Version 0.12.2
-------------- --------------

9
docs/quickstart.rst

@ -50,7 +50,14 @@ to tell your terminal the application to work with by exporting the
$ flask run $ flask run
* Running on http://127.0.0.1:5000/ * Running on http://127.0.0.1:5000/
If you are on Windows you need to use ``set`` instead of ``export``. If you are on Windows, the environment variable syntax depends on command line
interpreter. On Command Prompt::
C:\path\to\app>set FLASK_APP=hello.py
And on PowerShell::
PS C:\path\to\app> $env:FLASK_APP = "hello.py"
Alternatively you can use :command:`python -m flask`:: Alternatively you can use :command:`python -m flask`::

2
flask/_compat.py

@ -25,6 +25,7 @@ if not PY2:
itervalues = lambda d: iter(d.values()) itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items()) iteritems = lambda d: iter(d.items())
from inspect import getfullargspec as getargspec
from io import StringIO from io import StringIO
def reraise(tp, value, tb=None): def reraise(tp, value, tb=None):
@ -43,6 +44,7 @@ else:
itervalues = lambda d: d.itervalues() itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems() iteritems = lambda d: d.iteritems()
from inspect import getargspec
from cStringIO import StringIO from cStringIO import StringIO
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')

28
flask/cli.py

@ -22,13 +22,14 @@ from . import __version__
from ._compat import iteritems, reraise from ._compat import iteritems, reraise
from .globals import current_app from .globals import current_app
from .helpers import get_debug_flag from .helpers import get_debug_flag
from ._compat import getargspec
class NoAppException(click.UsageError): class NoAppException(click.UsageError):
"""Raised if an application cannot be found or loaded.""" """Raised if an application cannot be found or loaded."""
def find_best_app(module): def find_best_app(script_info, module):
"""Given a module instance this tries to find the best possible """Given a module instance this tries to find the best possible
application in the module or raises an exception. application in the module or raises an exception.
""" """
@ -60,8 +61,7 @@ def find_best_app(module):
if callable(app_factory): if callable(app_factory):
try: try:
app = app_factory() app = call_factory(app_factory, script_info)
if isinstance(app, Flask): if isinstance(app, Flask):
return app return app
except TypeError: except TypeError:
@ -79,6 +79,20 @@ def find_best_app(module):
) )
def call_factory(func, script_info):
"""Checks if the given app factory function has an argument named
``script_info`` or just a single argument and calls the function passing
``script_info`` if so. Otherwise, calls the function without any arguments
and returns the result.
"""
arguments = getargspec(func).args
if 'script_info' in arguments:
return func(script_info=script_info)
elif len(arguments) == 1:
return func(script_info)
return func()
def prepare_exec_for_file(filename): def prepare_exec_for_file(filename):
"""Given a filename this will try to calculate the python path, add it """Given a filename this will try to calculate the python path, add it
to the search path and return the actual module name that is expected. to the search path and return the actual module name that is expected.
@ -108,7 +122,7 @@ def prepare_exec_for_file(filename):
return '.'.join(module[::-1]) return '.'.join(module[::-1])
def locate_app(app_id): def locate_app(script_info, app_id):
"""Attempts to locate the application.""" """Attempts to locate the application."""
__traceback_hide__ = True __traceback_hide__ = True
if ':' in app_id: if ':' in app_id:
@ -134,7 +148,7 @@ def locate_app(app_id):
mod = sys.modules[module] mod = sys.modules[module]
if app_obj is None: if app_obj is None:
app = find_best_app(mod) app = find_best_app(script_info, mod)
else: else:
app = getattr(mod, app_obj, None) app = getattr(mod, app_obj, None)
if app is None: if app is None:
@ -259,7 +273,7 @@ class ScriptInfo(object):
if self._loaded_app is not None: if self._loaded_app is not None:
return self._loaded_app return self._loaded_app
if self.create_app is not None: if self.create_app is not None:
rv = self.create_app(self) rv = call_factory(self.create_app, self)
else: else:
if not self.app_import_path: if not self.app_import_path:
raise NoAppException( raise NoAppException(
@ -267,7 +281,7 @@ class ScriptInfo(object):
'the FLASK_APP environment variable.\n\nFor more ' 'the FLASK_APP environment variable.\n\nFor more '
'information see ' 'information see '
'http://flask.pocoo.org/docs/latest/quickstart/') 'http://flask.pocoo.org/docs/latest/quickstart/')
rv = locate_app(self.app_import_path) rv = locate_app(self, self.app_import_path)
debug = get_debug_flag() debug = get_debug_flag()
if debug is not None: if debug is not None:
rv.debug = debug rv.debug = debug

2
setup.py

@ -74,7 +74,7 @@ setup(
'Werkzeug>=0.7', 'Werkzeug>=0.7',
'Jinja2>=2.4', 'Jinja2>=2.4',
'itsdangerous>=0.21', 'itsdangerous>=0.21',
'click>=2.0', 'click>=4.0',
], ],
classifiers=[ classifiers=[
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',

62
tests/test_cli.py

@ -39,60 +39,75 @@ def test_cli_name(test_apps):
def test_find_best_app(test_apps): def test_find_best_app(test_apps):
"""Test if `find_best_app` behaves as expected with different combinations of input.""" """Test if `find_best_app` behaves as expected with different combinations of input."""
script_info = ScriptInfo()
class Module: class Module:
app = Flask('appname') app = Flask('appname')
assert find_best_app(Module) == Module.app assert find_best_app(script_info, Module) == Module.app
class Module: class Module:
application = Flask('appname') application = Flask('appname')
assert find_best_app(Module) == Module.application assert find_best_app(script_info, Module) == Module.application
class Module: class Module:
myapp = Flask('appname') myapp = Flask('appname')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
@staticmethod @staticmethod
def create_app(): def create_app():
return Flask('appname') return Flask('appname')
assert isinstance(find_best_app(Module), Flask) assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(Module).name == 'appname' assert find_best_app(script_info, Module).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'
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'
class Module: class Module:
@staticmethod @staticmethod
def make_app(): def make_app():
return Flask('appname') return Flask('appname')
assert isinstance(find_best_app(Module), Flask) assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(Module).name == 'appname' assert find_best_app(script_info, Module).name == 'appname'
class Module: class Module:
myapp = Flask('appname1') myapp = Flask('appname1')
@staticmethod @staticmethod
def create_app(): def create_app():
return Flask('appname2') return Flask('appname2')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
myapp = Flask('appname1') myapp = Flask('appname1')
@staticmethod @staticmethod
def create_app(foo): def create_app():
return Flask('appname2') return Flask('appname2')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
pass pass
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
class Module: class Module:
myapp1 = Flask('appname1') myapp1 = Flask('appname1')
myapp2 = Flask('appname2') myapp2 = Flask('appname2')
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
class Module: class Module:
@staticmethod @staticmethod
def create_app(foo): def create_app(foo, bar):
return Flask('appname2') return Flask('appname2')
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
def test_prepare_exec_for_file(test_apps): def test_prepare_exec_for_file(test_apps):
@ -117,13 +132,18 @@ def test_prepare_exec_for_file(test_apps):
def test_locate_app(test_apps): def test_locate_app(test_apps):
"""Test of locate_app.""" """Test of locate_app."""
assert locate_app("cliapp.app").name == "testapp" script_info = ScriptInfo()
assert locate_app("cliapp.app:testapp").name == "testapp" assert locate_app(script_info, "cliapp.app").name == "testapp"
assert locate_app("cliapp.multiapp:app1").name == "app1" assert locate_app(script_info, "cliapp.app:testapp").name == "testapp"
pytest.raises(NoAppException, locate_app, "notanpp.py") assert locate_app(script_info, "cliapp.multiapp:app1").name == "app1"
pytest.raises(NoAppException, locate_app, "cliapp/app") pytest.raises(NoAppException, locate_app,
pytest.raises(RuntimeError, locate_app, "cliapp.app:notanapp") script_info, "notanpp.py")
pytest.raises(NoAppException, locate_app, "cliapp.importerrorapp") pytest.raises(NoAppException, locate_app,
script_info, "cliapp/app")
pytest.raises(RuntimeError, locate_app,
script_info, "cliapp.app:notanapp")
pytest.raises(NoAppException, locate_app,
script_info, "cliapp.importerrorapp")
def test_find_default_import_path(test_apps, monkeypatch, tmpdir): def test_find_default_import_path(test_apps, monkeypatch, tmpdir):

8
tox.ini

@ -1,8 +1,6 @@
[tox] [tox]
envlist = {py26,py27,pypy}-{lowest,release,devel}{,-simplejson}, {py33,py34,py35,py36}-{release,devel}{,-simplejson} envlist = {py26,py27,pypy}-{lowest,release,devel}{,-simplejson}, {py33,py34,py35,py36}-{release,devel}{,-simplejson}
[testenv] [testenv]
passenv = LANG passenv = LANG
usedevelop=true usedevelop=true
@ -20,12 +18,18 @@ deps=
lowest: Werkzeug==0.7 lowest: Werkzeug==0.7
lowest: Jinja2==2.4 lowest: Jinja2==2.4
lowest: itsdangerous==0.21 lowest: itsdangerous==0.21
lowest: Click==4.0
lowest: blinker==1.0 lowest: blinker==1.0
release: blinker release: blinker
devel: git+https://github.com/pallets/werkzeug.git devel: git+https://github.com/pallets/werkzeug.git
devel: git+https://github.com/pallets/markupsafe.git
devel: git+https://github.com/pallets/jinja.git devel: git+https://github.com/pallets/jinja.git
devel: git+https://github.com/pallets/itsdangerous.git devel: git+https://github.com/pallets/itsdangerous.git
devel: git+https://github.com/pallets/click.git
devel: git+https://github.com/jek/blinker.git devel: git+https://github.com/jek/blinker.git
simplejson: simplejson simplejson: simplejson
[testenv:docs] [testenv:docs]

Loading…
Cancel
Save