| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  |     tests.test_cli | 
					
						
							|  |  |  |     ~~~~~~~~~~~~~~ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 02:57:40 +08:00
										 |  |  |     :copyright: © 2010 by the Pallets team. | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     :license: BSD, see LICENSE for more details. | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2018-02-09 02:57:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | # This file was part of Flask-CLI and was modified under the terms of | 
					
						
							|  |  |  | # its Revised BSD License. Copyright © 2015 CERN. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | from __future__ import absolute_import | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-06 01:32:00 +08:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | import ssl | 
					
						
							| 
									
										
										
										
											2016-06-06 01:32:00 +08:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | from functools import partial | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import click | 
					
						
							|  |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | from _pytest.monkeypatch import notset | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | from click.testing import CliRunner | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | from flask import Flask, current_app | 
					
						
							| 
									
										
										
										
											2018-01-11 05:53:45 +08:00
										 |  |  | from flask.cli import ( | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  |     AppGroup, FlaskGroup, NoAppException, ScriptInfo, dotenv, find_best_app, | 
					
						
							|  |  |  |     get_version, load_dotenv, locate_app, prepare_import, run_command, | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     with_appcontext | 
					
						
							| 
									
										
										
										
											2018-01-11 05:53:45 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | cwd = os.getcwd() | 
					
						
							|  |  |  | test_path = os.path.abspath(os.path.join( | 
					
						
							|  |  |  |     os.path.dirname(__file__), 'test_apps' | 
					
						
							|  |  |  | )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:24:43 +08:00
										 |  |  | @pytest.fixture | 
					
						
							|  |  |  | def runner(): | 
					
						
							|  |  |  |     return CliRunner() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | def test_cli_name(test_apps): | 
					
						
							| 
									
										
										
										
											2016-05-25 03:06:34 +08:00
										 |  |  |     """Make sure the CLI object's name is the app's name and not the app itself""" | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     from cliapp.app import testapp | 
					
						
							|  |  |  |     assert testapp.cli.name == testapp.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_find_best_app(test_apps): | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     """Test if `find_best_app` behaves as expected with different combinations of input.""" | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     script_info = ScriptInfo() | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |         app = Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert find_best_app(script_info, Module) == Module.app | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |         application = Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert find_best_app(script_info, Module) == Module.application | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |         myapp = Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert find_best_app(script_info, Module) == Module.myapp | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(): | 
					
						
							|  |  |  |             return Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     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): | 
					
						
							|  |  |  |             return Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     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') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert isinstance(find_best_app(script_info, Module), Flask) | 
					
						
							|  |  |  |     assert find_best_app(script_info, Module).name == 'appname' | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def make_app(): | 
					
						
							|  |  |  |             return Flask('appname') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert isinstance(find_best_app(script_info, Module), Flask) | 
					
						
							|  |  |  |     assert find_best_app(script_info, Module).name == 'appname' | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							|  |  |  |         myapp = Flask('appname1') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(): | 
					
						
							|  |  |  |             return Flask('appname2') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert find_best_app(script_info, Module) == Module.myapp | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							|  |  |  |         myapp = Flask('appname1') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |         @staticmethod | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |         def create_app(): | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |             return Flask('appname2') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     assert find_best_app(script_info, Module) == Module.myapp | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, script_info, Module) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         myapp1 = Flask('appname1') | 
					
						
							|  |  |  |         myapp2 = Flask('appname2') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, script_info, Module) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |         def create_app(foo, bar): | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |             return Flask('appname2') | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, script_info, Module) | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-25 07:05:57 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(): | 
					
						
							|  |  |  |             raise TypeError('bad bad factory!') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pytest.raises(TypeError, find_best_app, script_info, Module) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | @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. | 
					
						
							| 
									
										
										
										
											2016-06-06 01:32:00 +08:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |     original_path = sys.path[:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reset_path(): | 
					
						
							|  |  |  |         sys.path[:] = original_path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request.addfinalizer(reset_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert prepare_import(value) == result | 
					
						
							|  |  |  |     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'), | 
					
						
							| 
									
										
										
										
											2017-07-15 11:34:23 +08:00
										 |  |  |     # strip whitespace | 
					
						
							|  |  |  |     ('cliapp.factory', ' create_app () ', 'app'), | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | )) | 
					
						
							|  |  |  | 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")'), | 
					
						
							| 
									
										
										
										
											2017-07-15 11:34:23 +08:00
										 |  |  |     # invalid identifier | 
					
						
							|  |  |  |     ('cliapp.factory', 'create_app('), | 
					
						
							|  |  |  |     # no app returned | 
					
						
							|  |  |  |     ('cliapp.factory', 'no_app'), | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |     # nested import error | 
					
						
							|  |  |  |     ('cliapp.importerrorapp', None), | 
					
						
							|  |  |  |     # not a Python file | 
					
						
							|  |  |  |     ('cliapp.message.txt', None), | 
					
						
							|  |  |  | )) | 
					
						
							|  |  |  | def test_locate_app_raises(test_apps, iname, aname): | 
					
						
							|  |  |  |     info = ScriptInfo() | 
					
						
							| 
									
										
										
										
											2016-06-06 01:32:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 00:41:10 +08:00
										 |  |  |     with pytest.raises(NoAppException): | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |         locate_app(info, iname, aname) | 
					
						
							| 
									
										
										
										
											2016-06-04 00:41:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | def test_locate_app_suppress_raise(): | 
					
						
							|  |  |  |     info = ScriptInfo() | 
					
						
							|  |  |  |     app = locate_app(info, 'notanapp.py', None, raise_if_not_found=False) | 
					
						
							|  |  |  |     assert app is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # only direct import error is suppressed | 
					
						
							|  |  |  |     with pytest.raises(NoAppException): | 
					
						
							|  |  |  |         locate_app( | 
					
						
							|  |  |  |             info, 'cliapp.importerrorapp', None, raise_if_not_found=False | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2016-06-07 20:03:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  | def test_get_version(test_apps, capsys): | 
					
						
							|  |  |  |     """Test of get_version.""" | 
					
						
							|  |  |  |     from flask import __version__ as flask_ver | 
					
						
							|  |  |  |     from sys import version as py_ver | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  |     class MockCtx(object): | 
					
						
							|  |  |  |         resilient_parsing = False | 
					
						
							|  |  |  |         color = None | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  |         def exit(self): return | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  |     ctx = MockCtx() | 
					
						
							|  |  |  |     get_version(ctx, None, "test") | 
					
						
							|  |  |  |     out, err = capsys.readouterr() | 
					
						
							|  |  |  |     assert flask_ver in out | 
					
						
							|  |  |  |     assert py_ver in out | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  | def test_scriptinfo(test_apps, monkeypatch): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     """Test of ScriptInfo.""" | 
					
						
							|  |  |  |     obj = ScriptInfo(app_import_path="cliapp.app:testapp") | 
					
						
							|  |  |  |     assert obj.load_app().name == "testapp" | 
					
						
							|  |  |  |     assert obj.load_app().name == "testapp" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_app(info): | 
					
						
							|  |  |  |         return Flask("createapp") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     obj = ScriptInfo(create_app=create_app) | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							|  |  |  |     assert app.name == "createapp" | 
					
						
							|  |  |  |     assert obj.load_app() == app | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  |     obj = ScriptInfo() | 
					
						
							| 
									
										
										
										
											2017-06-16 21:59:37 +08:00
										 |  |  |     pytest.raises(NoAppException, obj.load_app) | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # import app from wsgi.py in current directory | 
					
						
							| 
									
										
										
										
											2017-06-16 21:59:37 +08:00
										 |  |  |     monkeypatch.chdir(os.path.abspath(os.path.join( | 
					
						
							|  |  |  |         os.path.dirname(__file__), 'test_apps', 'helloworld' | 
					
						
							|  |  |  |     ))) | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  |     obj = ScriptInfo() | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							|  |  |  |     assert app.name == 'hello' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # import app from app.py in current directory | 
					
						
							| 
									
										
										
										
											2017-06-16 21:59:37 +08:00
										 |  |  |     monkeypatch.chdir(os.path.abspath(os.path.join( | 
					
						
							|  |  |  |         os.path.dirname(__file__), 'test_apps', 'cliapp' | 
					
						
							|  |  |  |     ))) | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  |     obj = ScriptInfo() | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							|  |  |  |     assert app.name == 'testapp' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:24:43 +08:00
										 |  |  | def test_with_appcontext(runner): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     """Test of with_appcontext.""" | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     @click.command() | 
					
						
							|  |  |  |     @with_appcontext | 
					
						
							|  |  |  |     def testcmd(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     obj = ScriptInfo(create_app=lambda info: Flask("testapp")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(testcmd, obj=obj) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert result.output == 'testapp\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:24:43 +08:00
										 |  |  | def test_appgroup(runner): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     """Test of with_appcontext.""" | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     @click.group(cls=AppGroup) | 
					
						
							|  |  |  |     def cli(): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.command(with_appcontext=True) | 
					
						
							|  |  |  |     def test(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.group() | 
					
						
							|  |  |  |     def subgroup(): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @subgroup.command(with_appcontext=True) | 
					
						
							|  |  |  |     def test2(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     obj = ScriptInfo(create_app=lambda info: Flask("testappgroup")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(cli, ['test'], obj=obj) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert result.output == 'testappgroup\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(cli, ['subgroup', 'test2'], obj=obj) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert result.output == 'testappgroup\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:24:43 +08:00
										 |  |  | def test_flaskgroup(runner): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     """Test FlaskGroup.""" | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     def create_app(info): | 
					
						
							|  |  |  |         return Flask("flaskgroup") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @click.group(cls=FlaskGroup, create_app=create_app) | 
					
						
							|  |  |  |     def cli(**params): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.command() | 
					
						
							|  |  |  |     def test(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(cli, ['test']) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert result.output == 'flaskgroup\n' | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | def test_print_exceptions(runner): | 
					
						
							| 
									
										
										
										
											2017-03-17 03:56:12 +08:00
										 |  |  |     """Print the stacktrace if the CLI.""" | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-17 03:56:12 +08:00
										 |  |  |     def create_app(info): | 
					
						
							|  |  |  |         raise Exception("oh no") | 
					
						
							|  |  |  |         return Flask("flaskgroup") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @click.group(cls=FlaskGroup, create_app=create_app) | 
					
						
							|  |  |  |     def cli(**params): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(cli, ['--help']) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert 'Exception: oh no' in result.output | 
					
						
							|  |  |  |     assert 'Traceback' in result.output | 
					
						
							| 
									
										
										
										
											2017-04-26 04:13:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  | class TestRoutes: | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |     @pytest.fixture | 
					
						
							|  |  |  |     def invoke(self, runner): | 
					
						
							|  |  |  |         def create_app(info): | 
					
						
							|  |  |  |             app = Flask(__name__) | 
					
						
							|  |  |  |             app.testing = True | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |             @app.route('/get_post/<int:x>/<int:y>', methods=['GET', 'POST']) | 
					
						
							|  |  |  |             def yyy_get_post(x, y): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             @app.route('/zzz_post', methods=['POST']) | 
					
						
							|  |  |  |             def aaa_post(): | 
					
						
							|  |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |             return app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cli = FlaskGroup(create_app=create_app) | 
					
						
							|  |  |  |         return partial(runner.invoke, cli) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def expect_order(self, order, output): | 
					
						
							|  |  |  |         # skip the header and match the start of each row | 
					
						
							|  |  |  |         for expect, line in zip(order, output.splitlines()[2:]): | 
					
						
							|  |  |  |             # do this instead of startswith for nicer pytest output | 
					
						
							|  |  |  |             assert line[:len(expect)] == expect | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_simple(self, invoke): | 
					
						
							|  |  |  |         result = invoke(['routes']) | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  |         assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |         self.expect_order( | 
					
						
							|  |  |  |             ['aaa_post', 'static', 'yyy_get_post'], | 
					
						
							|  |  |  |             result.output | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_sort(self, invoke): | 
					
						
							|  |  |  |         default_output = invoke(['routes']).output | 
					
						
							|  |  |  |         endpoint_output = invoke(['routes', '-s', 'endpoint']).output | 
					
						
							|  |  |  |         assert default_output == endpoint_output | 
					
						
							|  |  |  |         self.expect_order( | 
					
						
							|  |  |  |             ['static', 'yyy_get_post', 'aaa_post'], | 
					
						
							|  |  |  |             invoke(['routes', '-s', 'methods']).output | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.expect_order( | 
					
						
							|  |  |  |             ['yyy_get_post', 'static', 'aaa_post'], | 
					
						
							|  |  |  |             invoke(['routes', '-s', 'rule']).output | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.expect_order( | 
					
						
							|  |  |  |             ['aaa_post', 'yyy_get_post', 'static'], | 
					
						
							|  |  |  |             invoke(['routes', '-s', 'match']).output | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_all_methods(self, invoke): | 
					
						
							|  |  |  |         output = invoke(['routes']).output | 
					
						
							|  |  |  |         assert 'GET, HEAD, OPTIONS, POST' not in output | 
					
						
							|  |  |  |         output = invoke(['routes', '--all-methods']).output | 
					
						
							|  |  |  |         assert 'GET, HEAD, OPTIONS, POST' in output | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | need_dotenv = pytest.mark.skipif( | 
					
						
							|  |  |  |     dotenv is None, reason='dotenv is not installed' | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @need_dotenv | 
					
						
							|  |  |  | def test_load_dotenv(monkeypatch): | 
					
						
							|  |  |  |     # can't use monkeypatch.delitem since the keys don't exist yet | 
					
						
							|  |  |  |     for item in ('FOO', 'BAR', 'SPAM'): | 
					
						
							|  |  |  |         monkeypatch._setitem.append((os.environ, item, notset)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     monkeypatch.setenv('EGGS', '3') | 
					
						
							|  |  |  |     monkeypatch.chdir(os.path.join(test_path, 'cliapp', 'inner1')) | 
					
						
							|  |  |  |     load_dotenv() | 
					
						
							|  |  |  |     assert os.getcwd() == test_path | 
					
						
							|  |  |  |     # .flaskenv doesn't overwrite .env | 
					
						
							|  |  |  |     assert os.environ['FOO'] == 'env' | 
					
						
							|  |  |  |     # set only in .flaskenv | 
					
						
							|  |  |  |     assert os.environ['BAR'] == 'bar' | 
					
						
							|  |  |  |     # set only in .env | 
					
						
							|  |  |  |     assert os.environ['SPAM'] == '1' | 
					
						
							|  |  |  |     # set manually, files don't overwrite | 
					
						
							|  |  |  |     assert os.environ['EGGS'] == '3' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @need_dotenv | 
					
						
							|  |  |  | def test_dotenv_path(monkeypatch): | 
					
						
							|  |  |  |     for item in ('FOO', 'BAR', 'EGGS'): | 
					
						
							|  |  |  |         monkeypatch._setitem.append((os.environ, item, notset)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cwd = os.getcwd() | 
					
						
							|  |  |  |     load_dotenv(os.path.join(test_path, '.flaskenv')) | 
					
						
							|  |  |  |     assert os.getcwd() == cwd | 
					
						
							|  |  |  |     assert 'FOO' in os.environ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dotenv_optional(monkeypatch): | 
					
						
							|  |  |  |     monkeypatch.setattr('flask.cli.dotenv', None) | 
					
						
							|  |  |  |     monkeypatch.chdir(test_path) | 
					
						
							|  |  |  |     load_dotenv() | 
					
						
							|  |  |  |     assert 'FOO' not in os.environ | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-28 23:07:53 +08:00
										 |  |  | @need_dotenv | 
					
						
							|  |  |  | def test_disable_dotenv_from_env(monkeypatch, runner): | 
					
						
							|  |  |  |     monkeypatch.chdir(test_path) | 
					
						
							|  |  |  |     monkeypatch.setitem(os.environ, 'FLASK_SKIP_DOTENV', '1') | 
					
						
							|  |  |  |     runner.invoke(FlaskGroup()) | 
					
						
							|  |  |  |     assert 'FOO' not in os.environ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | def test_run_cert_path(): | 
					
						
							|  |  |  |     # no key | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context('run', ['--cert', __file__]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # no cert | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context('run', ['--key', __file__]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctx = run_command.make_context( | 
					
						
							|  |  |  |         'run', ['--cert', __file__, '--key', __file__]) | 
					
						
							|  |  |  |     assert ctx.params['cert'] == (__file__, __file__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_run_cert_adhoc(monkeypatch): | 
					
						
							|  |  |  |     monkeypatch.setitem(sys.modules, 'OpenSSL', None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # pyOpenSSL not installed | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context('run', ['--cert', 'adhoc']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # pyOpenSSL installed | 
					
						
							|  |  |  |     monkeypatch.setitem(sys.modules, 'OpenSSL', types.ModuleType('OpenSSL')) | 
					
						
							|  |  |  |     ctx = run_command.make_context('run', ['--cert', 'adhoc']) | 
					
						
							|  |  |  |     assert ctx.params['cert'] == 'adhoc' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # no key with adhoc | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context('run', ['--cert', 'adhoc', '--key', __file__]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_run_cert_import(monkeypatch): | 
					
						
							|  |  |  |     monkeypatch.setitem(sys.modules, 'not_here', None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # ImportError | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context('run', ['--cert', 'not_here']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # not an SSLContext | 
					
						
							| 
									
										
										
										
											2018-05-16 20:21:19 +08:00
										 |  |  |     if sys.version_info >= (2, 7, 9): | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  |         with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |             run_command.make_context('run', ['--cert', 'flask']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # SSLContext | 
					
						
							| 
									
										
										
										
											2018-05-16 20:21:19 +08:00
										 |  |  |     if sys.version_info < (2, 7, 9): | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  |         ssl_context = object() | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     monkeypatch.setitem(sys.modules, 'ssl_context', ssl_context) | 
					
						
							|  |  |  |     ctx = run_command.make_context('run', ['--cert', 'ssl_context']) | 
					
						
							|  |  |  |     assert ctx.params['cert'] is ssl_context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # no --key with SSLContext | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context( | 
					
						
							|  |  |  |             'run', ['--cert', 'ssl_context', '--key', __file__]) |