|
|
@ -11,7 +11,8 @@ |
|
|
|
# the Revised BSD License. |
|
|
|
# the Revised BSD License. |
|
|
|
# Copyright (C) 2015 CERN. |
|
|
|
# Copyright (C) 2015 CERN. |
|
|
|
# |
|
|
|
# |
|
|
|
from __future__ import absolute_import, print_function |
|
|
|
from __future__ import absolute_import |
|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
|
import os |
|
|
|
import sys |
|
|
|
import sys |
|
|
|
from functools import partial |
|
|
|
from functools import partial |
|
|
@ -19,11 +20,10 @@ from functools import partial |
|
|
|
import click |
|
|
|
import click |
|
|
|
import pytest |
|
|
|
import pytest |
|
|
|
from click.testing import CliRunner |
|
|
|
from click.testing import CliRunner |
|
|
|
from flask import Flask, current_app |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from flask.cli import cli, AppGroup, FlaskGroup, NoAppException, ScriptInfo, \ |
|
|
|
from flask import Flask, current_app |
|
|
|
find_best_app, locate_app, with_appcontext, prepare_exec_for_file, \ |
|
|
|
from flask.cli import AppGroup, FlaskGroup, NoAppException, ScriptInfo, \ |
|
|
|
find_default_import_path, get_version |
|
|
|
find_best_app, get_version, locate_app, prepare_import, with_appcontext |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture |
|
|
|
@pytest.fixture |
|
|
@ -125,78 +125,104 @@ def test_find_best_app(test_apps): |
|
|
|
pytest.raises(NoAppException, find_best_app, script_info, Module) |
|
|
|
pytest.raises(NoAppException, find_best_app, script_info, Module) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_prepare_exec_for_file(test_apps): |
|
|
|
cwd = os.getcwd() |
|
|
|
"""Expect the correct path to be set and the correct module name to be returned. |
|
|
|
test_path = os.path.abspath(os.path.join( |
|
|
|
|
|
|
|
os.path.dirname(__file__), 'test_apps' |
|
|
|
:func:`prepare_exec_for_file` has a side effect, where |
|
|
|
)) |
|
|
|
the parent directory of given file is added to `sys.path`. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('value,path,result', ( |
|
|
|
|
|
|
|
('test', cwd, 'test'), |
|
|
|
|
|
|
|
('test.py', cwd, 'test'), |
|
|
|
|
|
|
|
('a/test', os.path.join(cwd, 'a'), 'test'), |
|
|
|
|
|
|
|
('test/__init__.py', cwd, 'test'), |
|
|
|
|
|
|
|
('test/__init__', cwd, 'test'), |
|
|
|
|
|
|
|
# nested package |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
os.path.join(test_path, 'cliapp', 'inner1', '__init__'), |
|
|
|
|
|
|
|
test_path, 'cliapp.inner1' |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
os.path.join(test_path, 'cliapp', 'inner1', 'inner2'), |
|
|
|
|
|
|
|
test_path, 'cliapp.inner1.inner2' |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
# dotted name |
|
|
|
|
|
|
|
('test.a.b', cwd, 'test.a.b'), |
|
|
|
|
|
|
|
(os.path.join(test_path, 'cliapp.app'), test_path, 'cliapp.app'), |
|
|
|
|
|
|
|
# not a Python file, will be caught during import |
|
|
|
|
|
|
|
( |
|
|
|
|
|
|
|
os.path.join(test_path, 'cliapp', 'message.txt'), |
|
|
|
|
|
|
|
test_path, 'cliapp.message.txt' |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
def test_prepare_import(request, value, path, result): |
|
|
|
|
|
|
|
"""Expect the correct path to be set and the correct import and app names |
|
|
|
|
|
|
|
to be returned. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:func:`prepare_exec_for_file` has a side effect where the parent directory |
|
|
|
|
|
|
|
of the given import is added to :data:`sys.path`. This is reset after the |
|
|
|
|
|
|
|
test runs. |
|
|
|
""" |
|
|
|
""" |
|
|
|
realpath = os.path.realpath('/tmp/share/test.py') |
|
|
|
original_path = sys.path[:] |
|
|
|
dirname = os.path.dirname(realpath) |
|
|
|
|
|
|
|
assert prepare_exec_for_file('/tmp/share/test.py') == 'test' |
|
|
|
def reset_path(): |
|
|
|
assert dirname in sys.path |
|
|
|
sys.path[:] = original_path |
|
|
|
|
|
|
|
|
|
|
|
realpath = os.path.realpath('/tmp/share/__init__.py') |
|
|
|
request.addfinalizer(reset_path) |
|
|
|
dirname = os.path.dirname(os.path.dirname(realpath)) |
|
|
|
|
|
|
|
assert prepare_exec_for_file('/tmp/share/__init__.py') == 'share' |
|
|
|
assert prepare_import(value) == result |
|
|
|
assert dirname in sys.path |
|
|
|
assert sys.path[0] == path |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('iname,aname,result', ( |
|
|
|
|
|
|
|
('cliapp.app', None, 'testapp'), |
|
|
|
|
|
|
|
('cliapp.app', 'testapp', 'testapp'), |
|
|
|
|
|
|
|
('cliapp.factory', None, 'app'), |
|
|
|
|
|
|
|
('cliapp.factory', 'create_app', 'app'), |
|
|
|
|
|
|
|
('cliapp.factory', 'create_app()', 'app'), |
|
|
|
|
|
|
|
# no script_info |
|
|
|
|
|
|
|
('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'), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
def test_locate_app(test_apps, iname, aname, result): |
|
|
|
|
|
|
|
info = ScriptInfo() |
|
|
|
|
|
|
|
info.data['test'] = 'spam' |
|
|
|
|
|
|
|
assert locate_app(info, iname, aname).name == result |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('iname,aname', ( |
|
|
|
|
|
|
|
('notanapp.py', None), |
|
|
|
|
|
|
|
('cliapp/app', None), |
|
|
|
|
|
|
|
('cliapp.app', 'notanapp'), |
|
|
|
|
|
|
|
# not enough arguments |
|
|
|
|
|
|
|
('cliapp.factory', 'create_app2("foo")'), |
|
|
|
|
|
|
|
# nested import error |
|
|
|
|
|
|
|
('cliapp.importerrorapp', None), |
|
|
|
|
|
|
|
# not a Python file |
|
|
|
|
|
|
|
('cliapp.message.txt', None), |
|
|
|
|
|
|
|
# space before arg list |
|
|
|
|
|
|
|
('cliapp.factory', 'create_app ()'), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
def test_locate_app_raises(test_apps, iname, aname): |
|
|
|
|
|
|
|
info = ScriptInfo() |
|
|
|
|
|
|
|
|
|
|
|
with pytest.raises(NoAppException): |
|
|
|
with pytest.raises(NoAppException): |
|
|
|
prepare_exec_for_file('/tmp/share/test.txt') |
|
|
|
locate_app(info, iname, aname) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_locate_app(test_apps): |
|
|
|
def test_locate_app_suppress_raise(): |
|
|
|
"""Test of locate_app.""" |
|
|
|
info = ScriptInfo() |
|
|
|
script_info = ScriptInfo() |
|
|
|
app = locate_app(info, 'notanapp.py', None, raise_if_not_found=False) |
|
|
|
assert locate_app(script_info, "cliapp.app").name == "testapp" |
|
|
|
assert app is None |
|
|
|
assert locate_app(script_info, "cliapp.app:testapp").name == "testapp" |
|
|
|
|
|
|
|
assert locate_app(script_info, "cliapp.factory").name == "create_app" |
|
|
|
# only direct import error is suppressed |
|
|
|
assert locate_app( |
|
|
|
with pytest.raises(NoAppException): |
|
|
|
script_info, "cliapp.factory").name == "create_app" |
|
|
|
locate_app( |
|
|
|
assert locate_app( |
|
|
|
info, 'cliapp.importerrorapp', None, raise_if_not_found=False |
|
|
|
script_info, "cliapp.factory:create_app").name == "create_app" |
|
|
|
) |
|
|
|
assert locate_app( |
|
|
|
|
|
|
|
script_info, "cliapp.factory:create_app()").name == "create_app" |
|
|
|
|
|
|
|
assert locate_app( |
|
|
|
|
|
|
|
script_info, "cliapp.factory:create_app2('foo', 'bar')" |
|
|
|
|
|
|
|
).name == "create_app2_foo_bar" |
|
|
|
|
|
|
|
assert locate_app( |
|
|
|
|
|
|
|
script_info, "cliapp.factory:create_app2('foo', 'bar', )" |
|
|
|
|
|
|
|
).name == "create_app2_foo_bar" |
|
|
|
|
|
|
|
assert locate_app( |
|
|
|
|
|
|
|
script_info, "cliapp.factory:create_app3('baz', 'qux')" |
|
|
|
|
|
|
|
).name == "create_app3_baz_qux" |
|
|
|
|
|
|
|
assert locate_app(script_info, "cliapp.multiapp:app1").name == "app1" |
|
|
|
|
|
|
|
pytest.raises( |
|
|
|
|
|
|
|
NoAppException, locate_app, script_info, "notanpp.py") |
|
|
|
|
|
|
|
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.factory:create_app2('foo')") |
|
|
|
|
|
|
|
pytest.raises( |
|
|
|
|
|
|
|
NoAppException, locate_app, |
|
|
|
|
|
|
|
script_info, "cliapp.factory:create_app ()") |
|
|
|
|
|
|
|
pytest.raises( |
|
|
|
|
|
|
|
NoAppException, locate_app, script_info, "cliapp.importerrorapp") |
|
|
|
|
|
|
|
assert locate_app( |
|
|
|
|
|
|
|
script_info, "notanpp.py", raise_if_not_found=False |
|
|
|
|
|
|
|
) is None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_find_default_import_path(test_apps, monkeypatch, tmpdir): |
|
|
|
|
|
|
|
"""Test of find_default_import_path.""" |
|
|
|
|
|
|
|
monkeypatch.delitem(os.environ, 'FLASK_APP', raising=False) |
|
|
|
|
|
|
|
assert find_default_import_path() == None |
|
|
|
|
|
|
|
monkeypatch.setitem(os.environ, 'FLASK_APP', 'notanapp') |
|
|
|
|
|
|
|
assert find_default_import_path() == 'notanapp' |
|
|
|
|
|
|
|
tmpfile = tmpdir.join('testapp.py') |
|
|
|
|
|
|
|
tmpfile.write('') |
|
|
|
|
|
|
|
monkeypatch.setitem(os.environ, 'FLASK_APP', str(tmpfile)) |
|
|
|
|
|
|
|
expect_rv = prepare_exec_for_file(str(tmpfile)) |
|
|
|
|
|
|
|
assert find_default_import_path() == expect_rv |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_version(test_apps, capsys): |
|
|
|
def test_get_version(test_apps, capsys): |
|
|
|