diff --git a/CHANGES.rst b/CHANGES.rst index 367cfb668..5658080c3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,8 @@ Unreleased - Inform Python < 3.12 how to handle ``itms-services`` URIs correctly, rather than using an overly-broad workaround in Werkzeug that caused some redirect URIs to be passed on without encoding. :issue:`2828` +- Type annotation for ``Rule.endpoint`` and other uses of ``endpoint`` is + ``Any``. :issue:`2836` Version 3.0.2 diff --git a/src/werkzeug/routing/exceptions.py b/src/werkzeug/routing/exceptions.py index b63fe5b9c..eeabd4ed1 100644 --- a/src/werkzeug/routing/exceptions.py +++ b/src/werkzeug/routing/exceptions.py @@ -59,7 +59,7 @@ def __init__(self, path_info: str) -> None: class RequestAliasRedirect(RoutingException): # noqa: B903 """This rule is an alias and wants to redirect to the canonical URL.""" - def __init__(self, matched_values: t.Mapping[str, t.Any], endpoint: str) -> None: + def __init__(self, matched_values: t.Mapping[str, t.Any], endpoint: t.Any) -> None: super().__init__() self.matched_values = matched_values self.endpoint = endpoint @@ -72,7 +72,7 @@ class BuildError(RoutingException, LookupError): def __init__( self, - endpoint: str, + endpoint: t.Any, values: t.Mapping[str, t.Any], method: str | None, adapter: MapAdapter | None = None, @@ -93,7 +93,10 @@ def _score_rule(rule: Rule) -> float: [ 0.98 * difflib.SequenceMatcher( - None, rule.endpoint, self.endpoint + # endpoints can be any type, compare as strings + None, + str(rule.endpoint), + str(self.endpoint), ).ratio(), 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), 0.01 * bool(rule.methods and self.method in rule.methods), diff --git a/src/werkzeug/routing/map.py b/src/werkzeug/routing/map.py index 73671bf94..4d15e8824 100644 --- a/src/werkzeug/routing/map.py +++ b/src/werkzeug/routing/map.py @@ -104,7 +104,7 @@ def __init__( host_matching: bool = False, ) -> None: self._matcher = StateMachineMatcher(merge_slashes) - self._rules_by_endpoint: dict[str, list[Rule]] = {} + self._rules_by_endpoint: dict[t.Any, list[Rule]] = {} self._remap = True self._remap_lock = self.lock_class() @@ -131,7 +131,7 @@ def merge_slashes(self) -> bool: def merge_slashes(self, value: bool) -> None: self._matcher.merge_slashes = value - def is_endpoint_expecting(self, endpoint: str, *arguments: str) -> bool: + def is_endpoint_expecting(self, endpoint: t.Any, *arguments: str) -> bool: """Iterate over all rules and check if the endpoint expects the arguments provided. This is for example useful if you have some URLs that expect a language code and others that do not and @@ -155,7 +155,7 @@ def is_endpoint_expecting(self, endpoint: str, *arguments: str) -> bool: def _rules(self) -> list[Rule]: return [rule for rules in self._rules_by_endpoint.values() for rule in rules] - def iter_rules(self, endpoint: str | None = None) -> t.Iterator[Rule]: + def iter_rules(self, endpoint: t.Any | None = None) -> t.Iterator[Rule]: """Iterate over all rules or the rules of an endpoint. :param endpoint: if provided only the rules for that endpoint @@ -470,14 +470,14 @@ def application(environ, start_response): raise @t.overload - def match( # type: ignore + def match( self, path_info: str | None = None, method: str | None = None, return_rule: t.Literal[False] = False, query_args: t.Mapping[str, t.Any] | str | None = None, websocket: bool | None = None, - ) -> tuple[str, t.Mapping[str, t.Any]]: ... + ) -> tuple[t.Any, t.Mapping[str, t.Any]]: ... @t.overload def match( @@ -496,7 +496,7 @@ def match( return_rule: bool = False, query_args: t.Mapping[str, t.Any] | str | None = None, websocket: bool | None = None, - ) -> tuple[str | Rule, t.Mapping[str, t.Any]]: + ) -> tuple[t.Any | Rule, t.Mapping[str, t.Any]]: """The usage is simple: you just pass the match method the current path info as well as the method (which defaults to `GET`). The following things can then happen: @@ -770,7 +770,7 @@ def make_redirect_url( def make_alias_redirect_url( self, path: str, - endpoint: str, + endpoint: t.Any, values: t.Mapping[str, t.Any], method: str, query_args: t.Mapping[str, t.Any] | str, @@ -786,7 +786,7 @@ def make_alias_redirect_url( def _partial_build( self, - endpoint: str, + endpoint: t.Any, values: t.Mapping[str, t.Any], method: str | None, append_unknown: bool, @@ -827,7 +827,7 @@ def _partial_build( def build( self, - endpoint: str, + endpoint: t.Any, values: t.Mapping[str, t.Any] | None = None, method: str | None = None, force_external: bool = False, diff --git a/src/werkzeug/routing/rules.py b/src/werkzeug/routing/rules.py index 75323357c..6a02f8d3e 100644 --- a/src/werkzeug/routing/rules.py +++ b/src/werkzeug/routing/rules.py @@ -453,7 +453,7 @@ def __init__( subdomain: str | None = None, methods: t.Iterable[str] | None = None, build_only: bool = False, - endpoint: str | None = None, + endpoint: t.Any | None = None, strict_slashes: bool | None = None, merge_slashes: bool | None = None, redirect_to: str | t.Callable[..., str] | None = None, @@ -493,7 +493,7 @@ def __init__( ) self.methods = methods - self.endpoint: str = endpoint # type: ignore + self.endpoint: t.Any = endpoint self.redirect_to = redirect_to if defaults: