diff --git a/sanic/app.py b/sanic/app.py index 566266e0..c801cd3d 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -960,6 +960,10 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta): # Execution # -------------------------------------------------------------------- # + def make_coffee(self, *args, **kwargs): + self.state.coffee = True + self.run(*args, **kwargs) + def run( self, host: Optional[str] = None, @@ -1562,7 +1566,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta): extra.update(self.config.MOTD_DISPLAY) logo = ( - get_logo() + get_logo(coffee=self.state.coffee) if self.config.LOGO == "" or self.config.LOGO is True else self.config.LOGO ) diff --git a/sanic/application/logo.py b/sanic/application/logo.py index 9e3bb2fa..56b8c0b1 100644 --- a/sanic/application/logo.py +++ b/sanic/application/logo.py @@ -10,6 +10,15 @@ BASE_LOGO = """ Build Fast. Run Fast. """ +COFFEE_LOGO = """\033[48;2;255;13;104m \033[0m +\033[38;2;255;255;255;48;2;255;13;104m ▄████████▄ \033[0m +\033[38;2;255;255;255;48;2;255;13;104m ██ ██▀▀▄ \033[0m +\033[38;2;255;255;255;48;2;255;13;104m ███████████ █ \033[0m +\033[38;2;255;255;255;48;2;255;13;104m ███████████▄▄▀ \033[0m +\033[38;2;255;255;255;48;2;255;13;104m ▀███████▀ \033[0m +\033[48;2;255;13;104m \033[0m +Dark roast. No sugar.""" + COLOR_LOGO = """\033[48;2;255;13;104m \033[0m \033[38;2;255;255;255;48;2;255;13;104m ▄███ █████ ██ \033[0m \033[38;2;255;255;255;48;2;255;13;104m ██ \033[0m @@ -32,9 +41,9 @@ FULL_COLOR_LOGO = """ ansi_pattern = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") -def get_logo(full=False): +def get_logo(full=False, coffee=False): logo = ( - (FULL_COLOR_LOGO if full else COLOR_LOGO) + (FULL_COLOR_LOGO if full else (COFFEE_LOGO if coffee else COLOR_LOGO)) if sys.stdout.isatty() else BASE_LOGO ) diff --git a/sanic/application/state.py b/sanic/application/state.py index b03c30da..eb180708 100644 --- a/sanic/application/state.py +++ b/sanic/application/state.py @@ -34,6 +34,7 @@ class Mode(StrEnum): class ApplicationState: app: Sanic asgi: bool = field(default=False) + coffee: bool = field(default=False) fast: bool = field(default=False) host: str = field(default="") mode: Mode = field(default=Mode.PRODUCTION) diff --git a/tests/test_coffee.py b/tests/test_coffee.py new file mode 100644 index 00000000..6143f17f --- /dev/null +++ b/tests/test_coffee.py @@ -0,0 +1,48 @@ +import logging + +from unittest.mock import patch + +import pytest + +from sanic.application.logo import COFFEE_LOGO, get_logo +from sanic.exceptions import SanicException + + +def has_sugar(value): + if value: + raise SanicException("I said no sugar please") + + return False + + +@pytest.mark.parametrize("sugar", (True, False)) +def test_no_sugar(sugar): + if sugar: + with pytest.raises(SanicException): + assert has_sugar(sugar) + else: + assert not has_sugar(sugar) + + +def test_get_logo_returns_expected_logo(): + with patch("sys.stdout.isatty") as isatty: + isatty.return_value = True + logo = get_logo(coffee=True) + assert logo is COFFEE_LOGO + + +def test_logo_true(app, caplog): + @app.after_server_start + async def shutdown(*_): + app.stop() + + with patch("sys.stdout.isatty") as isatty: + isatty.return_value = True + with caplog.at_level(logging.DEBUG): + app.make_coffee() + + # Only in the regular logo + assert " ▄███ █████ ██ " not in caplog.text + + # Only in the coffee logo + assert " ██ ██▀▀▄ " in caplog.text