diff --git a/sanic/cli/app.py b/sanic/cli/app.py index 95a572a8..db830e09 100644 --- a/sanic/cli/app.py +++ b/sanic/cli/app.py @@ -113,6 +113,14 @@ Or, a path to a directory to run as a simple HTTP server: delimiter = ":" if ":" in self.args.module else "." module_name, app_name = self.args.module.rsplit(delimiter, 1) + if module_name == "" and os.path.isdir(self.args.module): + raise ValueError( + "App not found.\n" + " Please use --simple if you are passing a " + "directory to sanic.\n" + f" eg. sanic {self.args.module} --simple" + ) + if app_name.endswith("()"): self.args.factory = True app_name = app_name[:-2] @@ -125,9 +133,18 @@ Or, a path to a directory to run as a simple HTTP server: app_type_name = type(app).__name__ if not isinstance(app, Sanic): + if callable(app): + solution = f"sanic {self.args.module} --factory" + raise ValueError( + "Module is not a Sanic app, it is a" + f"{app_type_name}\n" + " If this callable returns a" + f"Sanic instance try: \n{solution}" + ) + raise ValueError( f"Module is not a Sanic app, it is a {app_type_name}\n" - f" Perhaps you meant {self.args.module}.app?" + f" Perhaps you meant {self.args.module}:app?" ) except ImportError as e: if module_name.startswith(e.name): diff --git a/tests/fake/factory.py b/tests/fake/factory.py new file mode 100644 index 00000000..17a815cd --- /dev/null +++ b/tests/fake/factory.py @@ -0,0 +1,6 @@ +from sanic import Sanic + + +def run(): + app = Sanic("FactoryTest") + return app diff --git a/tests/test_cli.py b/tests/test_cli.py index 7ec1c28c..b12bb414 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -57,6 +57,22 @@ def test_server_run(appname): assert firstline == b"Goin' Fast @ http://127.0.0.1:8000" +def test_error_with_function_as_instance_without_factory_arg(): + command = ["sanic", "fake.factory.run"] + out, err, exitcode = capture(command) + assert b"try: \nsanic fake.factory.run --factory" in err + assert exitcode != 1 + + +def test_error_with_path_as_instance_without_simple_arg(): + command = ["sanic", "./fake/"] + out, err, exitcode = capture(command) + assert ( + b"Please use --simple if you are passing a directory to sanic." in err + ) + assert exitcode != 1 + + @pytest.mark.parametrize( "cmd", (