Skip to content

Commit

Permalink
v23.3 Deprecation Removal (#2717)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins committed Mar 26, 2023
1 parent a8c2d77 commit d680af3
Show file tree
Hide file tree
Showing 26 changed files with 180 additions and 598 deletions.
19 changes: 8 additions & 11 deletions sanic/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@
from sanic.handlers import ErrorHandler
from sanic.helpers import Default, _default
from sanic.http import Stage
from sanic.log import (
LOGGING_CONFIG_DEFAULTS,
deprecation,
error_logger,
logger,
)
from sanic.log import LOGGING_CONFIG_DEFAULTS, error_logger, logger
from sanic.middleware import Middleware, MiddlewareLocation
from sanic.mixins.listeners import ListenerEvent
from sanic.mixins.startup import StartupMixin
Expand Down Expand Up @@ -1584,17 +1579,19 @@ async def _startup(self):
self.signalize(self.config.TOUCHUP)
self.finalize()

route_names = [route.name for route in self.router.routes]
route_names = [route.extra.ident for route in self.router.routes]
duplicates = {
name for name in route_names if route_names.count(name) > 1
}
if duplicates:
names = ", ".join(duplicates)
deprecation(
f"Duplicate route names detected: {names}. In the future, "
"Sanic will enforce uniqueness in route naming.",
23.3,
message = (
f"Duplicate route names detected: {names}. You should rename "
"one or more of them explicitly by using the `name` param, "
"or changing the implicit name derived from the class and "
"function name. For more details, please see ___."
)
raise ServerError(message)

Sanic._check_uvloop_conflict()

Expand Down
13 changes: 13 additions & 0 deletions sanic/blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class Blueprint(BaseSanic):
"_future_listeners",
"_future_exceptions",
"_future_signals",
"copied_from",
"ctx",
"exceptions",
"host",
Expand All @@ -118,6 +119,7 @@ def __init__(
):
super().__init__(name=name)
self.reset()
self.copied_from = ""
self.ctx = SimpleNamespace()
self.host = host
self.strict_slashes = strict_slashes
Expand Down Expand Up @@ -213,6 +215,7 @@ def copy(
self.reset()
new_bp = deepcopy(self)
new_bp.name = name
new_bp.copied_from = self.name

if not isinstance(url_prefix, Default):
new_bp.url_prefix = url_prefix
Expand Down Expand Up @@ -352,6 +355,16 @@ def register(self, app, options):

registered.add(apply_route)
route = app._apply_route(apply_route)

# If it is a copied BP, then make sure all of the names of routes
# matchup with the new BP name
if self.copied_from:
for r in route:
r.name = r.name.replace(self.copied_from, self.name)
r.extra.ident = r.extra.ident.replace(
self.copied_from, self.name
)

operation = (
routes.extend if isinstance(route, list) else routes.append
)
Expand Down
40 changes: 2 additions & 38 deletions sanic/cli/app.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import logging
import os
import shutil
import sys

from argparse import Namespace
from functools import partial
from textwrap import indent
from typing import List, Union, cast
from typing import List, Union

from sanic.app import Sanic
from sanic.application.logo import get_logo
from sanic.cli.arguments import Group
from sanic.cli.base import SanicArgumentParser, SanicHelpFormatter
from sanic.cli.inspector import make_inspector_parser
from sanic.cli.inspector_client import InspectorClient
from sanic.log import Colors, error_logger
from sanic.log import error_logger
from sanic.worker.loader import AppLoader


Expand Down Expand Up @@ -103,10 +102,6 @@ def run(self, parse_args=None):
self.args.target, self.args.factory, self.args.simple, self.args
)

if self.args.inspect or self.args.inspect_raw or self.args.trigger:
self._inspector_legacy(app_loader)
return

try:
app = self._get_app(app_loader)
kwargs = self._build_run_kwargs()
Expand All @@ -117,38 +112,10 @@ def run(self, parse_args=None):
app.prepare(**kwargs, version=http_version)
if self.args.single:
serve = Sanic.serve_single
elif self.args.legacy:
serve = Sanic.serve_legacy
else:
serve = partial(Sanic.serve, app_loader=app_loader)
serve(app)

def _inspector_legacy(self, app_loader: AppLoader):
host = port = None
target = cast(str, self.args.target)
if ":" in target:
maybe_host, maybe_port = target.rsplit(":", 1)
if maybe_port.isnumeric():
host, port = maybe_host, int(maybe_port)
if not host:
app = self._get_app(app_loader)
host, port = app.config.INSPECTOR_HOST, app.config.INSPECTOR_PORT

action = self.args.trigger or "info"

InspectorClient(
str(host), int(port or 6457), False, self.args.inspect_raw, ""
).do(action)
sys.stdout.write(
f"\n{Colors.BOLD}{Colors.YELLOW}WARNING:{Colors.END} "
"You are using the legacy CLI command that will be removed in "
f"{Colors.RED}v23.3{Colors.END}. See "
"https://sanic.dev/en/guide/release-notes/v22.12.html"
"#deprecations-and-removals or checkout the new "
"style commands:\n\n\t"
f"{Colors.YELLOW}sanic inspect --help{Colors.END}\n"
)

def _inspector(self):
args = sys.argv[2:]
self.args, unknown = self.parser.parse_known_args(args=args)
Expand Down Expand Up @@ -202,8 +169,6 @@ def _precheck(self):
)
error_logger.error(message)
sys.exit(1)
if self.args.inspect or self.args.inspect_raw:
logging.disable(logging.CRITICAL)

def _get_app(self, app_loader: AppLoader):
try:
Expand Down Expand Up @@ -251,7 +216,6 @@ def _build_run_kwargs(self):
"workers": self.args.workers,
"auto_tls": self.args.auto_tls,
"single_process": self.args.single,
"legacy": self.args.legacy,
}

for maybe_arg in ("auto_reload", "dev"):
Expand Down
31 changes: 0 additions & 31 deletions sanic/cli/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,6 @@ def attach(self):
"a directory\n(module arg should be a path)"
),
)
group.add_argument(
"--inspect",
dest="inspect",
action="store_true",
help=("Inspect the state of a running instance, human readable"),
)
group.add_argument(
"--inspect-raw",
dest="inspect_raw",
action="store_true",
help=("Inspect the state of a running instance, JSON output"),
)
group.add_argument(
"--trigger-reload",
dest="trigger",
action="store_const",
const="reload",
help=("Trigger worker processes to reload"),
)
group.add_argument(
"--trigger-shutdown",
dest="trigger",
action="store_const",
const="shutdown",
help=("Trigger all processes to shutdown"),
)


class HTTPVersionGroup(Group):
Expand Down Expand Up @@ -247,11 +221,6 @@ def attach(self):
action="store_true",
help="Do not use multiprocessing, run server in a single process",
)
self.container.add_argument(
"--legacy",
action="store_true",
help="Use the legacy server manager",
)
self.add_bool_arguments(
"--access-logs",
dest="access_log",
Expand Down
12 changes: 4 additions & 8 deletions sanic/handlers/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from typing import Dict, List, Optional, Tuple, Type

from sanic.errorpages import BaseRenderer, TextRenderer, exception_response
from sanic.log import deprecation, error_logger
from sanic.exceptions import ServerError
from sanic.log import error_logger
from sanic.models.handler_types import RouteHandler
from sanic.response import text

Expand Down Expand Up @@ -43,16 +44,11 @@ def _add(
if name is None:
name = "__ALL_ROUTES__"

error_logger.warning(
message = (
f"Duplicate exception handler definition on: route={name} "
f"and exception={exc}"
)
deprecation(
"A duplicate exception handler definition was discovered. "
"This may cause unintended consequences. A warning has been "
"issued now, but it will not be allowed starting in v23.3.",
23.3,
)
raise ServerError(message)
self.cached_handlers[key] = handler

def add(self, exception, handler, route_names: Optional[List[str]] = None):
Expand Down
87 changes: 4 additions & 83 deletions sanic/mixins/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,16 @@
from sanic.http.constants import HTTP
from sanic.http.tls import get_ssl_context, process_to_context
from sanic.http.tls.context import SanicSSLContext
from sanic.log import Colors, deprecation, error_logger, logger
from sanic.log import Colors, error_logger, logger
from sanic.models.handler_types import ListenerType
from sanic.server import Signal as ServerSignal
from sanic.server import try_use_uvloop
from sanic.server.async_server import AsyncioServer
from sanic.server.events import trigger_events
from sanic.server.legacy import watchdog
from sanic.server.loop import try_windows_loop
from sanic.server.protocols.http_protocol import HttpProtocol
from sanic.server.protocols.websocket_protocol import WebSocketProtocol
from sanic.server.runners import serve, serve_multiple, serve_single
from sanic.server.runners import serve
from sanic.server.socket import configure_socket, remove_unix_socket
from sanic.worker.loader import AppLoader
from sanic.worker.manager import WorkerManager
Expand Down Expand Up @@ -135,7 +134,6 @@ def run(
motd_display: Optional[Dict[str, str]] = None,
auto_tls: bool = False,
single_process: bool = False,
legacy: bool = False,
) -> None:
"""
Run the HTTP Server and listen until keyboard interrupt or term
Expand Down Expand Up @@ -197,13 +195,10 @@ def run(
motd_display=motd_display,
auto_tls=auto_tls,
single_process=single_process,
legacy=legacy,
)

if single_process:
serve = self.__class__.serve_single
elif legacy:
serve = self.__class__.serve_legacy
else:
serve = self.__class__.serve
serve(primary=self) # type: ignore
Expand Down Expand Up @@ -235,7 +230,6 @@ def prepare(
coffee: bool = False,
auto_tls: bool = False,
single_process: bool = False,
legacy: bool = False,
) -> None:
if version == 3 and self.state.server_info:
raise RuntimeError(
Expand Down Expand Up @@ -264,13 +258,10 @@ def prepare(
"or auto-reload"
)

if single_process and legacy:
raise RuntimeError("Cannot run single process and legacy mode")

if register_sys_signals is False and not (single_process or legacy):
if register_sys_signals is False and not single_process:
raise RuntimeError(
"Cannot run Sanic.serve with register_sys_signals=False. "
"Use either Sanic.serve_single or Sanic.serve_legacy."
"Use Sanic.serve_single."
)

if motd_display:
Expand Down Expand Up @@ -956,76 +947,6 @@ def serve_single(cls, primary: Optional[Sanic] = None) -> None:
cls._cleanup_env_vars()
cls._cleanup_apps()

@classmethod
def serve_legacy(cls, primary: Optional[Sanic] = None) -> None:
apps = list(cls._app_registry.values())

if not primary:
try:
primary = apps[0]
except IndexError:
raise RuntimeError("Did not find any applications.")

reloader_start = primary.listeners.get("reload_process_start")
reloader_stop = primary.listeners.get("reload_process_stop")
# We want to run auto_reload if ANY of the applications have it enabled
if (
cls.should_auto_reload()
and os.environ.get("SANIC_SERVER_RUNNING") != "true"
): # no cov
loop = new_event_loop()
trigger_events(reloader_start, loop, primary)
reload_dirs: Set[Path] = primary.state.reload_dirs.union(
*(app.state.reload_dirs for app in apps)
)
watchdog(1.0, reload_dirs)
trigger_events(reloader_stop, loop, primary)
return

# This exists primarily for unit testing
if not primary.state.server_info: # no cov
for app in apps:
app.state.server_info.clear()
return

primary_server_info = primary.state.server_info[0]
primary.before_server_start(partial(primary._start_servers, apps=apps))

deprecation(
f"{Colors.YELLOW}Running {Colors.SANIC}Sanic {Colors.YELLOW}w/ "
f"LEGACY manager.{Colors.END} Support for will be dropped in "
"version 23.3.",
23.3,
)
try:
primary_server_info.stage = ServerStage.SERVING

if primary.state.workers > 1 and os.name != "posix": # no cov
logger.warning(
f"Multiprocessing is currently not supported on {os.name},"
" using workers=1 instead"
)
primary.state.workers = 1
if primary.state.workers == 1:
serve_single(primary_server_info.settings)
elif primary.state.workers == 0:
raise RuntimeError("Cannot serve with no workers")
else:
serve_multiple(
primary_server_info.settings, primary.state.workers
)
except BaseException:
error_logger.exception(
"Experienced exception while trying to serve"
)
raise
finally:
primary_server_info.stage = ServerStage.STOPPED
logger.info("Server Stopped")

cls._cleanup_env_vars()
cls._cleanup_apps()

async def _start_servers(
self,
primary: Sanic,
Expand Down
Loading

0 comments on commit d680af3

Please sign in to comment.