| 
									
										
										
										
											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. | 
					
						
							| 
									
										
										
										
											2023-08-22 00:39:10 +08:00
										 |  |  | import importlib.metadata | 
					
						
							| 
									
										
										
										
											2016-06-06 01:32:00 +08:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2023-08-22 00:39:10 +08:00
										 |  |  | import platform | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  | from pathlib import Path | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-01 23:35:03 +08:00
										 |  |  | from flask import Blueprint | 
					
						
							|  |  |  | from flask import current_app | 
					
						
							|  |  |  | from flask import Flask | 
					
						
							|  |  |  | from flask.cli import AppGroup | 
					
						
							|  |  |  | from flask.cli import find_best_app | 
					
						
							|  |  |  | from flask.cli import FlaskGroup | 
					
						
							|  |  |  | from flask.cli import get_version | 
					
						
							|  |  |  | from flask.cli import load_dotenv | 
					
						
							|  |  |  | from flask.cli import locate_app | 
					
						
							|  |  |  | from flask.cli import NoAppException | 
					
						
							|  |  |  | from flask.cli import prepare_import | 
					
						
							|  |  |  | from flask.cli import run_command | 
					
						
							|  |  |  | from flask.cli import ScriptInfo | 
					
						
							|  |  |  | from flask.cli import with_appcontext | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  | cwd = Path.cwd() | 
					
						
							|  |  |  | test_path = (Path(__file__) / ".." / "test_apps").resolve() | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     assert testapp.cli.name == testapp.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_find_best_app(test_apps): | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         app = Flask("appname") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert find_best_app(Module) == Module.app | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         application = Flask("appname") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert find_best_app(Module) == Module.application | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         myapp = Flask("appname") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert find_best_app(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(): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             return Flask("appname") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     app = find_best_app(Module) | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     assert isinstance(app, Flask) | 
					
						
							|  |  |  |     assert app.name == "appname" | 
					
						
							| 
									
										
										
										
											2017-05-24 04:46:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 10:39:13 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(**kwargs): | 
					
						
							|  |  |  |             return Flask("appname") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     app = find_best_app(Module) | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     assert isinstance(app, Flask) | 
					
						
							|  |  |  |     assert app.name == "appname" | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def make_app(): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             return Flask("appname") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     app = find_best_app(Module) | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     assert isinstance(app, Flask) | 
					
						
							|  |  |  |     assert app.name == "appname" | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         myapp = Flask("appname1") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             return Flask("appname2") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert find_best_app(Module) == Module.myapp | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         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(): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             return Flask("appname2") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert find_best_app(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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, Module) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 03:46:01 +08:00
										 |  |  |     class Module: | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         myapp1 = Flask("appname1") | 
					
						
							|  |  |  |         myapp2 = Flask("appname2") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, 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): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             return Flask("appname2") | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     pytest.raises(NoAppException, find_best_app, Module) | 
					
						
							| 
									
										
										
										
											2017-05-23 03:30:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-25 07:05:57 +08:00
										 |  |  |     class Module: | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def create_app(): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             raise TypeError("bad bad factory!") | 
					
						
							| 
									
										
										
										
											2017-11-25 07:05:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     pytest.raises(TypeError, find_best_app, Module) | 
					
						
							| 
									
										
										
										
											2017-11-25 07:05:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | @pytest.mark.parametrize( | 
					
						
							|  |  |  |     "value,path,result", | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |     ( | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         ("test", cwd, "test"), | 
					
						
							|  |  |  |         ("test.py", cwd, "test"), | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |         ("a/test", cwd / "a", "test"), | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         ("test/__init__.py", cwd, "test"), | 
					
						
							|  |  |  |         ("test/__init__", cwd, "test"), | 
					
						
							|  |  |  |         # nested package | 
					
						
							|  |  |  |         ( | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |             test_path / "cliapp" / "inner1" / "__init__", | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             test_path, | 
					
						
							|  |  |  |             "cliapp.inner1", | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         ( | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |             test_path / "cliapp" / "inner1" / "inner2", | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             test_path, | 
					
						
							|  |  |  |             "cliapp.inner1.inner2", | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         # dotted name | 
					
						
							|  |  |  |         ("test.a.b", cwd, "test.a.b"), | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |         (test_path / "cliapp.app", test_path, "cliapp.app"), | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         # not a Python file, will be caught during import | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |         (test_path / "cliapp" / "message.txt", test_path, "cliapp.message.txt"), | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |     ), | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     assert sys.path[0] == str(path) | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | @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"), | 
					
						
							|  |  |  |         ("cliapp.factory", 'create_app2("foo", "bar")', "app2_foo_bar"), | 
					
						
							|  |  |  |         # trailing comma space | 
					
						
							|  |  |  |         ("cliapp.factory", 'create_app2("foo", "bar", )', "app2_foo_bar"), | 
					
						
							|  |  |  |         # strip whitespace | 
					
						
							|  |  |  |         ("cliapp.factory", " create_app () ", "app"), | 
					
						
							|  |  |  |     ), | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | def test_locate_app(test_apps, iname, aname, result): | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     assert locate_app(iname, aname).name == result | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | @pytest.mark.parametrize( | 
					
						
							|  |  |  |     "iname,aname", | 
					
						
							|  |  |  |     ( | 
					
						
							|  |  |  |         ("notanapp.py", None), | 
					
						
							|  |  |  |         ("cliapp/app", None), | 
					
						
							|  |  |  |         ("cliapp.app", "notanapp"), | 
					
						
							|  |  |  |         # not enough arguments | 
					
						
							|  |  |  |         ("cliapp.factory", 'create_app2("foo")'), | 
					
						
							|  |  |  |         # invalid identifier | 
					
						
							|  |  |  |         ("cliapp.factory", "create_app("), | 
					
						
							|  |  |  |         # no app returned | 
					
						
							|  |  |  |         ("cliapp.factory", "no_app"), | 
					
						
							|  |  |  |         # nested import error | 
					
						
							|  |  |  |         ("cliapp.importerrorapp", None), | 
					
						
							|  |  |  |         # not a Python file | 
					
						
							|  |  |  |         ("cliapp.message.txt", None), | 
					
						
							|  |  |  |     ), | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  | def test_locate_app_raises(test_apps, iname, aname): | 
					
						
							| 
									
										
										
										
											2016-06-04 00:41:10 +08:00
										 |  |  |     with pytest.raises(NoAppException): | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |         locate_app(iname, aname) | 
					
						
							| 
									
										
										
										
											2016-06-04 00:41:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  | def test_locate_app_suppress_raise(test_apps): | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |     app = locate_app("notanapp.py", None, raise_if_not_found=False) | 
					
						
							| 
									
										
										
										
											2017-07-15 10:27:45 +08:00
										 |  |  |     assert app is None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # only direct import error is suppressed | 
					
						
							|  |  |  |     with pytest.raises(NoAppException): | 
					
						
							| 
									
										
										
										
											2021-11-12 22:46:54 +08:00
										 |  |  |         locate_app("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): | 
					
						
							| 
									
										
										
										
											2020-04-05 00:43:06 +08:00
										 |  |  |     class MockCtx: | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  |         resilient_parsing = False | 
					
						
							|  |  |  |         color = None | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +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() | 
					
						
							| 
									
										
										
										
											2023-08-22 00:39:10 +08:00
										 |  |  |     assert f"Python {platform.python_version()}" in out | 
					
						
							|  |  |  |     assert f"Flask {importlib.metadata.version('flask')}" in out | 
					
						
							|  |  |  |     assert f"Werkzeug {importlib.metadata.version('werkzeug')}" in out | 
					
						
							| 
									
										
										
										
											2016-08-20 23:43:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  | def test_scriptinfo(test_apps, monkeypatch): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     obj = ScriptInfo(app_import_path="cliapp.app:testapp") | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     app = obj.load_app() | 
					
						
							|  |  |  |     assert app.name == "testapp" | 
					
						
							|  |  |  |     assert obj.load_app() is app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # import app with module's absolute path | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     cli_app_path = str(test_path / "cliapp" / "app.py") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     obj = ScriptInfo(app_import_path=cli_app_path) | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert app.name == "testapp" | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     assert obj.load_app() is app | 
					
						
							| 
									
										
										
										
											2020-04-05 02:39:03 +08:00
										 |  |  |     obj = ScriptInfo(app_import_path=f"{cli_app_path}:testapp") | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     app = obj.load_app() | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert app.name == "testapp" | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     assert obj.load_app() is app | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     def create_app(): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |         return Flask("createapp") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     obj = ScriptInfo(create_app=create_app) | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							|  |  |  |     assert app.name == "createapp" | 
					
						
							| 
									
										
										
										
											2018-10-24 21:13:11 +08:00
										 |  |  |     assert obj.load_app() is app | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     monkeypatch.chdir(test_path / "helloworld") | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  |     obj = ScriptInfo() | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert app.name == "hello" | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # import app from app.py in current directory | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     monkeypatch.chdir(test_path / "cliapp") | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  |     obj = ScriptInfo() | 
					
						
							|  |  |  |     app = obj.load_app() | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert app.name == "testapp" | 
					
						
							| 
									
										
										
										
											2017-06-16 02:27:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  | def test_app_cli_has_app_context(app, runner): | 
					
						
							|  |  |  |     def _param_cb(ctx, param, value): | 
					
						
							|  |  |  |         # current_app should be available in parameter callbacks | 
					
						
							|  |  |  |         return bool(current_app) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @app.cli.command() | 
					
						
							|  |  |  |     @click.argument("value", callback=_param_cb) | 
					
						
							|  |  |  |     def check(value): | 
					
						
							|  |  |  |         app = click.get_current_context().obj.load_app() | 
					
						
							|  |  |  |         # the loaded app should be the same as current_app | 
					
						
							|  |  |  |         same_app = current_app._get_current_object() is app | 
					
						
							| 
									
										
										
										
											2022-06-30 12:11:58 +08:00
										 |  |  |         return same_app, value | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cli = FlaskGroup(create_app=lambda: app) | 
					
						
							|  |  |  |     result = runner.invoke(cli, ["check", "x"], standalone_mode=False) | 
					
						
							| 
									
										
										
										
											2022-06-30 12:11:58 +08:00
										 |  |  |     assert result.return_value == (True, True) | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 19:24:43 +08:00
										 |  |  | def test_with_appcontext(runner): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     @click.command() | 
					
						
							|  |  |  |     @with_appcontext | 
					
						
							|  |  |  |     def testcmd(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     obj = ScriptInfo(create_app=lambda: Flask("testapp")) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(testcmd, obj=obj) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert result.output == "testapp\n" | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  | def test_appgroup_app_context(runner): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     @click.group(cls=AppGroup) | 
					
						
							|  |  |  |     def cli(): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  |     @cli.command() | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     def test(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.group() | 
					
						
							|  |  |  |     def subgroup(): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  |     @subgroup.command() | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     def test2(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     obj = ScriptInfo(create_app=lambda: Flask("testappgroup")) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     result = runner.invoke(cli, ["test"], obj=obj) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert result.output == "testappgroup\n" | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     result = runner.invoke(cli, ["subgroup", "test2"], obj=obj) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert result.output == "testappgroup\n" | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 02:14:22 +08:00
										 |  |  | def test_flaskgroup_app_context(runner): | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     def create_app(): | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |         return Flask("flaskgroup") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @click.group(cls=FlaskGroup, create_app=create_app) | 
					
						
							|  |  |  |     def cli(**params): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.command() | 
					
						
							|  |  |  |     def test(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     result = runner.invoke(cli, ["test"]) | 
					
						
							| 
									
										
										
										
											2016-05-17 01:36:55 +08:00
										 |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert result.output == "flaskgroup\n" | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  | @pytest.mark.parametrize("set_debug_flag", (True, False)) | 
					
						
							| 
									
										
										
										
											2018-05-09 00:05:55 +08:00
										 |  |  | def test_flaskgroup_debug(runner, set_debug_flag): | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     def create_app(): | 
					
						
							| 
									
										
										
										
											2018-05-09 00:05:55 +08:00
										 |  |  |         app = Flask("flaskgroup") | 
					
						
							|  |  |  |         app.debug = True | 
					
						
							|  |  |  |         return app | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @click.group(cls=FlaskGroup, create_app=create_app, set_debug_flag=set_debug_flag) | 
					
						
							|  |  |  |     def cli(**params): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cli.command() | 
					
						
							|  |  |  |     def test(): | 
					
						
							|  |  |  |         click.echo(str(current_app.debug)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     result = runner.invoke(cli, ["test"]) | 
					
						
							| 
									
										
										
										
											2018-05-09 00:05:55 +08:00
										 |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2020-04-05 02:39:03 +08:00
										 |  |  |     assert result.output == f"{not set_debug_flag}\n" | 
					
						
							| 
									
										
										
										
											2018-05-09 00:05:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 05:07:00 +08:00
										 |  |  | def test_flaskgroup_nested(app, runner): | 
					
						
							|  |  |  |     cli = click.Group("cli") | 
					
						
							|  |  |  |     flask_group = FlaskGroup(name="flask", create_app=lambda: app) | 
					
						
							|  |  |  |     cli.add_command(flask_group) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @flask_group.command() | 
					
						
							|  |  |  |     def show(): | 
					
						
							|  |  |  |         click.echo(current_app.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = runner.invoke(cli, ["flask", "show"]) | 
					
						
							|  |  |  |     assert result.output == "flask_test\n" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  | def test_no_command_echo_loading_error(): | 
					
						
							|  |  |  |     from flask.cli import cli | 
					
						
							| 
									
										
										
										
											2017-05-25 08:27:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-08 03:27:51 +08:00
										 |  |  |     try: | 
					
						
							|  |  |  |         runner = CliRunner(mix_stderr=False) | 
					
						
							|  |  |  |     except (DeprecationWarning, TypeError): | 
					
						
							|  |  |  |         # Click >= 8.2 | 
					
						
							|  |  |  |         runner = CliRunner() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  |     result = runner.invoke(cli, ["missing"]) | 
					
						
							|  |  |  |     assert result.exit_code == 2 | 
					
						
							|  |  |  |     assert "FLASK_APP" in result.stderr | 
					
						
							|  |  |  |     assert "Usage:" in result.stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_help_echo_loading_error(): | 
					
						
							|  |  |  |     from flask.cli import cli | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-08 03:27:51 +08:00
										 |  |  |     try: | 
					
						
							|  |  |  |         runner = CliRunner(mix_stderr=False) | 
					
						
							|  |  |  |     except (DeprecationWarning, TypeError): | 
					
						
							|  |  |  |         # Click >= 8.2 | 
					
						
							|  |  |  |         runner = CliRunner() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  |     result = runner.invoke(cli, ["--help"]) | 
					
						
							|  |  |  |     assert result.exit_code == 0 | 
					
						
							|  |  |  |     assert "FLASK_APP" in result.stderr | 
					
						
							|  |  |  |     assert "Usage:" in result.stdout | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_help_echo_exception(): | 
					
						
							| 
									
										
										
										
											2020-04-08 06:54:36 +08:00
										 |  |  |     def create_app(): | 
					
						
							| 
									
										
										
										
											2017-03-17 03:56:12 +08:00
										 |  |  |         raise Exception("oh no") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  |     cli = FlaskGroup(create_app=create_app) | 
					
						
							| 
									
										
										
										
											2024-11-08 03:27:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         runner = CliRunner(mix_stderr=False) | 
					
						
							|  |  |  |     except (DeprecationWarning, TypeError): | 
					
						
							|  |  |  |         # Click >= 8.2 | 
					
						
							|  |  |  |         runner = CliRunner() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     result = runner.invoke(cli, ["--help"]) | 
					
						
							| 
									
										
										
										
											2017-03-17 03:56:12 +08:00
										 |  |  |     assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2020-07-31 09:36:55 +08:00
										 |  |  |     assert "Exception: oh no" in result.stderr | 
					
						
							|  |  |  |     assert "Usage:" in result.stdout | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2022-07-03 12:02:00 +08:00
										 |  |  |     def app(self): | 
					
						
							|  |  |  |         app = Flask(__name__) | 
					
						
							| 
									
										
										
										
											2023-04-15 00:34:26 +08:00
										 |  |  |         app.add_url_rule( | 
					
						
							|  |  |  |             "/get_post/<int:x>/<int:y>", | 
					
						
							|  |  |  |             methods=["GET", "POST"], | 
					
						
							|  |  |  |             endpoint="yyy_get_post", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         app.add_url_rule("/zzz_post", methods=["POST"], endpoint="aaa_post") | 
					
						
							| 
									
										
										
										
											2022-07-03 12:02:00 +08:00
										 |  |  |         return app | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-03 12:02:00 +08:00
										 |  |  |     @pytest.fixture | 
					
						
							|  |  |  |     def invoke(self, app, runner): | 
					
						
							|  |  |  |         cli = FlaskGroup(create_app=lambda: app) | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |         return partial(runner.invoke, cli) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def expect_order(self, order, output): | 
					
						
							|  |  |  |         # skip the header and match the start of each row | 
					
						
							| 
									
										
										
										
											2025-05-13 23:31:54 +08:00
										 |  |  |         for expect, line in zip(order, output.splitlines()[2:], strict=False): | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |             # do this instead of startswith for nicer pytest output | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             assert line[: len(expect)] == expect | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_simple(self, invoke): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         result = invoke(["routes"]) | 
					
						
							| 
									
										
										
										
											2016-06-25 19:17:33 +08:00
										 |  |  |         assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         self.expect_order(["aaa_post", "static", "yyy_get_post"], result.output) | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-03 12:02:00 +08:00
										 |  |  |     def test_sort(self, app, invoke): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         default_output = invoke(["routes"]).output | 
					
						
							|  |  |  |         endpoint_output = invoke(["routes", "-s", "endpoint"]).output | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |         assert default_output == endpoint_output | 
					
						
							|  |  |  |         self.expect_order( | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             ["static", "yyy_get_post", "aaa_post"], | 
					
						
							|  |  |  |             invoke(["routes", "-s", "methods"]).output, | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |         ) | 
					
						
							|  |  |  |         self.expect_order( | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |             ["yyy_get_post", "static", "aaa_post"], | 
					
						
							|  |  |  |             invoke(["routes", "-s", "rule"]).output, | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-07-03 12:02:00 +08:00
										 |  |  |         match_order = [r.endpoint for r in app.url_map.iter_rules()] | 
					
						
							|  |  |  |         self.expect_order(match_order, invoke(["routes", "-s", "match"]).output) | 
					
						
							| 
									
										
										
										
											2017-04-26 05:15:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_all_methods(self, invoke): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 00:34:26 +08:00
										 |  |  |     def test_no_routes(self, runner): | 
					
						
							|  |  |  |         app = Flask(__name__, static_folder=None) | 
					
						
							|  |  |  |         cli = FlaskGroup(create_app=lambda: app) | 
					
						
							|  |  |  |         result = runner.invoke(cli, ["routes"]) | 
					
						
							| 
									
										
										
										
											2018-05-31 11:43:51 +08:00
										 |  |  |         assert result.exit_code == 0 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         assert "No routes were registered." in result.output | 
					
						
							| 
									
										
										
										
											2018-05-31 11:43:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 00:34:26 +08:00
										 |  |  |     def test_subdomain(self, runner): | 
					
						
							|  |  |  |         app = Flask(__name__, static_folder=None) | 
					
						
							|  |  |  |         app.add_url_rule("/a", subdomain="a", endpoint="a") | 
					
						
							|  |  |  |         app.add_url_rule("/b", subdomain="b", endpoint="b") | 
					
						
							|  |  |  |         cli = FlaskGroup(create_app=lambda: app) | 
					
						
							|  |  |  |         result = runner.invoke(cli, ["routes"]) | 
					
						
							|  |  |  |         assert result.exit_code == 0 | 
					
						
							|  |  |  |         assert "Subdomain" in result.output | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_host(self, runner): | 
					
						
							|  |  |  |         app = Flask(__name__, static_folder=None, host_matching=True) | 
					
						
							|  |  |  |         app.add_url_rule("/a", host="a", endpoint="a") | 
					
						
							|  |  |  |         app.add_url_rule("/b", host="b", endpoint="b") | 
					
						
							|  |  |  |         cli = FlaskGroup(create_app=lambda: app) | 
					
						
							|  |  |  |         result = runner.invoke(cli, ["routes"]) | 
					
						
							|  |  |  |         assert result.exit_code == 0 | 
					
						
							|  |  |  |         assert "Host" in result.output | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 00:46:20 +08:00
										 |  |  | def dotenv_not_available(): | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         import dotenv  # noqa: F401 | 
					
						
							|  |  |  |     except ImportError: | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | need_dotenv = pytest.mark.skipif( | 
					
						
							|  |  |  |     dotenv_not_available(), reason="dotenv is not installed" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @need_dotenv | 
					
						
							|  |  |  | def test_load_dotenv(monkeypatch): | 
					
						
							|  |  |  |     # can't use monkeypatch.delitem since the keys don't exist yet | 
					
						
							| 
									
										
										
										
											2021-03-10 21:40:29 +08:00
										 |  |  |     for item in ("FOO", "BAR", "SPAM", "HAM"): | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |         monkeypatch._setitem.append((os.environ, item, notset)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     monkeypatch.setenv("EGGS", "3") | 
					
						
							| 
									
										
										
										
											2020-04-07 21:46:53 +08:00
										 |  |  |     monkeypatch.chdir(test_path) | 
					
						
							| 
									
										
										
										
											2018-10-11 19:22:15 +08:00
										 |  |  |     assert load_dotenv() | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     assert Path.cwd() == test_path | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     # .flaskenv doesn't overwrite .env | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert os.environ["FOO"] == "env" | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     # set only in .flaskenv | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert os.environ["BAR"] == "bar" | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     # set only in .env | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert os.environ["SPAM"] == "1" | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     # set manually, files don't overwrite | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert os.environ["EGGS"] == "3" | 
					
						
							| 
									
										
										
										
											2021-03-10 21:40:29 +08:00
										 |  |  |     # test env file encoding | 
					
						
							|  |  |  |     assert os.environ["HAM"] == "火腿" | 
					
						
							| 
									
										
										
										
											2018-10-11 19:22:15 +08:00
										 |  |  |     # Non existent file should not load | 
					
						
							| 
									
										
										
										
											2024-11-08 03:27:51 +08:00
										 |  |  |     assert not load_dotenv("non-existent-file", load_defaults=False) | 
					
						
							| 
									
										
										
										
											2018-10-11 19:22:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | @need_dotenv | 
					
						
							|  |  |  | def test_dotenv_path(monkeypatch): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     for item in ("FOO", "BAR", "EGGS"): | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |         monkeypatch._setitem.append((os.environ, item, notset)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:34:32 +08:00
										 |  |  |     load_dotenv(test_path / ".flaskenv") | 
					
						
							|  |  |  |     assert Path.cwd() == cwd | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert "FOO" in os.environ | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_dotenv_optional(monkeypatch): | 
					
						
							| 
									
										
										
										
											2022-05-24 00:46:20 +08:00
										 |  |  |     monkeypatch.setitem(sys.modules, "dotenv", None) | 
					
						
							| 
									
										
										
										
											2017-07-15 13:37:53 +08:00
										 |  |  |     monkeypatch.chdir(test_path) | 
					
						
							|  |  |  |     load_dotenv() | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     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) | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     monkeypatch.setitem(os.environ, "FLASK_SKIP_DOTENV", "1") | 
					
						
							| 
									
										
										
										
											2018-04-28 23:07:53 +08:00
										 |  |  |     runner.invoke(FlaskGroup()) | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     assert "FOO" not in os.environ | 
					
						
							| 
									
										
										
										
											2018-04-28 23:07:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | def test_run_cert_path(): | 
					
						
							|  |  |  |     # no key | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--cert", __file__]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # no cert | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--key", __file__]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:52:01 +08:00
										 |  |  |     # cert specified first | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     ctx = run_command.make_context("run", ["--cert", __file__, "--key", __file__]) | 
					
						
							|  |  |  |     assert ctx.params["cert"] == (__file__, __file__) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:52:01 +08:00
										 |  |  |     # key specified first | 
					
						
							|  |  |  |     ctx = run_command.make_context("run", ["--key", __file__, "--cert", __file__]) | 
					
						
							|  |  |  |     assert ctx.params["cert"] == (__file__, __file__) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | def test_run_cert_adhoc(monkeypatch): | 
					
						
							| 
									
										
										
										
											2020-02-10 08:01:23 +08:00
										 |  |  |     monkeypatch.setitem(sys.modules, "cryptography", None) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-10 08:01:23 +08:00
										 |  |  |     # cryptography not installed | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--cert", "adhoc"]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-10 08:01:23 +08:00
										 |  |  |     # cryptography installed | 
					
						
							|  |  |  |     monkeypatch.setitem(sys.modules, "cryptography", types.ModuleType("cryptography")) | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     ctx = run_command.make_context("run", ["--cert", "adhoc"]) | 
					
						
							|  |  |  |     assert ctx.params["cert"] == "adhoc" | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # no key with adhoc | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--cert", "adhoc", "--key", __file__]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_run_cert_import(monkeypatch): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     monkeypatch.setitem(sys.modules, "not_here", None) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # ImportError | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--cert", "not_here"]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-05 00:25:54 +08:00
										 |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context("run", ["--cert", "flask"]) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # SSLContext | 
					
						
							| 
									
										
										
										
											2020-04-05 00:25:54 +08:00
										 |  |  |     ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |     monkeypatch.setitem(sys.modules, "ssl_context", ssl_context) | 
					
						
							|  |  |  |     ctx = run_command.make_context("run", ["--cert", "ssl_context"]) | 
					
						
							|  |  |  |     assert ctx.params["cert"] is ssl_context | 
					
						
							| 
									
										
										
										
											2018-01-23 04:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # no --key with SSLContext | 
					
						
							|  |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							| 
									
										
										
										
											2019-05-07 03:39:41 +08:00
										 |  |  |         run_command.make_context("run", ["--cert", "ssl_context", "--key", __file__]) | 
					
						
							| 
									
										
										
										
											2018-05-15 10:05:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 23:45:38 +08:00
										 |  |  | def test_run_cert_no_ssl(monkeypatch): | 
					
						
							| 
									
										
										
										
											2022-05-24 00:46:20 +08:00
										 |  |  |     monkeypatch.setitem(sys.modules, "ssl", None) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 23:45:38 +08:00
										 |  |  |     with pytest.raises(click.BadParameter): | 
					
						
							|  |  |  |         run_command.make_context("run", ["--cert", "not_here"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-15 10:05:54 +08:00
										 |  |  | def test_cli_blueprints(app): | 
					
						
							|  |  |  |     """Test blueprint commands register correctly to the application""" | 
					
						
							|  |  |  |     custom = Blueprint("custom", __name__, cli_group="customized") | 
					
						
							|  |  |  |     nested = Blueprint("nested", __name__) | 
					
						
							|  |  |  |     merged = Blueprint("merged", __name__, cli_group=None) | 
					
						
							|  |  |  |     late = Blueprint("late", __name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @custom.cli.command("custom") | 
					
						
							|  |  |  |     def custom_command(): | 
					
						
							|  |  |  |         click.echo("custom_result") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @nested.cli.command("nested") | 
					
						
							|  |  |  |     def nested_command(): | 
					
						
							|  |  |  |         click.echo("nested_result") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @merged.cli.command("merged") | 
					
						
							|  |  |  |     def merged_command(): | 
					
						
							|  |  |  |         click.echo("merged_result") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @late.cli.command("late") | 
					
						
							|  |  |  |     def late_command(): | 
					
						
							|  |  |  |         click.echo("late_result") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     app.register_blueprint(custom) | 
					
						
							|  |  |  |     app.register_blueprint(nested) | 
					
						
							|  |  |  |     app.register_blueprint(merged) | 
					
						
							|  |  |  |     app.register_blueprint(late, cli_group="late_registration") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     app_runner = app.test_cli_runner() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = app_runner.invoke(args=["customized", "custom"]) | 
					
						
							|  |  |  |     assert "custom_result" in result.output | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = app_runner.invoke(args=["nested", "nested"]) | 
					
						
							|  |  |  |     assert "nested_result" in result.output | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = app_runner.invoke(args=["merged"]) | 
					
						
							|  |  |  |     assert "merged_result" in result.output | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = app_runner.invoke(args=["late_registration", "late"]) | 
					
						
							|  |  |  |     assert "late_result" in result.output | 
					
						
							| 
									
										
										
										
											2019-05-31 23:48:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_cli_empty(app): | 
					
						
							|  |  |  |     """If a Blueprint's CLI group is empty, do not register it.""" | 
					
						
							|  |  |  |     bp = Blueprint("blue", __name__, cli_group="blue") | 
					
						
							|  |  |  |     app.register_blueprint(bp) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = app.test_cli_runner().invoke(args=["blue", "--help"]) | 
					
						
							| 
									
										
										
										
											2020-04-05 02:39:03 +08:00
										 |  |  |     assert result.exit_code == 2, f"Unexpected success:\n\n{result.output}" | 
					
						
							| 
									
										
										
										
											2024-01-26 10:08:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_run_exclude_patterns(): | 
					
						
							|  |  |  |     ctx = run_command.make_context("run", ["--exclude-patterns", __file__]) | 
					
						
							|  |  |  |     assert ctx.params["exclude_patterns"] == [__file__] |