]> jfr.im git - dlqueue.git/blobdiff - venv/lib/python3.11/site-packages/werkzeug/routing/rules.py
hello world
[dlqueue.git] / venv / lib / python3.11 / site-packages / werkzeug / routing / rules.py
diff --git a/venv/lib/python3.11/site-packages/werkzeug/routing/rules.py b/venv/lib/python3.11/site-packages/werkzeug/routing/rules.py
deleted file mode 100644 (file)
index 5c8184c..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-from __future__ import annotations
-
-import ast
-import re
-import typing as t
-from dataclasses import dataclass
-from string import Template
-from types import CodeType
-from urllib.parse import quote
-
-from ..datastructures import iter_multi_items
-from ..urls import _urlencode
-from .converters import ValidationError
-
-if t.TYPE_CHECKING:
-    from .converters import BaseConverter
-    from .map import Map
-
-
-class Weighting(t.NamedTuple):
-    number_static_weights: int
-    static_weights: list[tuple[int, int]]
-    number_argument_weights: int
-    argument_weights: list[int]
-
-
-@dataclass
-class RulePart:
-    """A part of a rule.
-
-    Rules can be represented by parts as delimited by `/` with
-    instances of this class representing those parts. The *content* is
-    either the raw content if *static* or a regex string to match
-    against. The *weight* can be used to order parts when matching.
-
-    """
-
-    content: str
-    final: bool
-    static: bool
-    suffixed: bool
-    weight: Weighting
-
-
-_part_re = re.compile(
-    r"""
-    (?:
-        (?P<slash>/)                                 # a slash
-      |
-        (?P<static>[^</]+)                           # static rule data
-      |
-        (?:
-          <
-            (?:
-              (?P<converter>[a-zA-Z_][a-zA-Z0-9_]*)   # converter name
-              (?:\((?P<arguments>.*?)\))?             # converter arguments
-              :                                       # variable delimiter
-            )?
-            (?P<variable>[a-zA-Z_][a-zA-Z0-9_]*)      # variable name
-           >
-        )
-    )
-    """,
-    re.VERBOSE,
-)
-
-_simple_rule_re = re.compile(r"<([^>]+)>")
-_converter_args_re = re.compile(
-    r"""
-    ((?P<name>\w+)\s*=\s*)?
-    (?P<value>
-        True|False|
-        \d+.\d+|
-        \d+.|
-        \d+|
-        [\w\d_.]+|
-        [urUR]?(?P<stringval>"[^"]*?"|'[^']*')
-    )\s*,
-    """,
-    re.VERBOSE,
-)
-
-
-_PYTHON_CONSTANTS = {"None": None, "True": True, "False": False}
-
-
-def _find(value: str, target: str, pos: int) -> int:
-    """Find the *target* in *value* after *pos*.
-
-    Returns the *value* length if *target* isn't found.
-    """
-    try:
-        return value.index(target, pos)
-    except ValueError:
-        return len(value)
-
-
-def _pythonize(value: str) -> None | bool | int | float | str:
-    if value in _PYTHON_CONSTANTS:
-        return _PYTHON_CONSTANTS[value]
-    for convert in int, float:
-        try:
-            return convert(value)  # type: ignore
-        except ValueError:
-            pass
-    if value[:1] == value[-1:] and value[0] in "\"'":
-        value = value[1:-1]
-    return str(value)
-
-
-def parse_converter_args(argstr: str) -> tuple[t.Tuple, dict[str, t.Any]]:
-    argstr += ","
-    args = []
-    kwargs = {}
-
-    for item in _converter_args_re.finditer(argstr):
-        value = item.group("stringval")
-        if value is None:
-            value = item.group("value")
-        value = _pythonize(value)
-        if not item.group("name"):
-            args.append(value)
-        else:
-            name = item.group("name")
-            kwargs[name] = value
-
-    return tuple(args), kwargs
-
-
-class RuleFactory:
-    """As soon as you have more complex URL setups it's a good idea to use rule
-    factories to avoid repetitive tasks.  Some of them are builtin, others can
-    be added by subclassing `RuleFactory` and overriding `get_rules`.
-    """
-
-    def get_rules(self, map: Map) -> t.Iterable[Rule]:
-        """Subclasses of `RuleFactory` have to override this method and return
-        an iterable of rules."""
-        raise NotImplementedError()
-
-
-class Subdomain(RuleFactory):
-    """All URLs provided by this factory have the subdomain set to a
-    specific domain. For example if you want to use the subdomain for
-    the current language this can be a good setup::
-
-        url_map = Map([
-            Rule('/', endpoint='#select_language'),
-            Subdomain('<string(length=2):lang_code>', [
-                Rule('/', endpoint='index'),
-                Rule('/about', endpoint='about'),
-                Rule('/help', endpoint='help')
-            ])
-        ])
-
-    All the rules except for the ``'#select_language'`` endpoint will now
-    listen on a two letter long subdomain that holds the language code
-    for the current request.
-    """
-
-    def __init__(self, subdomain: str, rules: t.Iterable[RuleFactory]) -> None:
-        self.subdomain = subdomain
-        self.rules = rules
-
-    def get_rules(self, map: Map) -> t.Iterator[Rule]:
-        for rulefactory in self.rules:
-            for rule in rulefactory.get_rules(map):
-                rule = rule.empty()
-                rule.subdomain = self.subdomain
-                yield rule
-
-
-class Submount(RuleFactory):
-    """Like `Subdomain` but prefixes the URL rule with a given string::
-
-        url_map = Map([
-            Rule('/', endpoint='index'),
-            Submount('/blog', [
-                Rule('/', endpoint='blog/index'),
-                Rule('/entry/<entry_slug>', endpoint='blog/show')
-            ])
-        ])
-
-    Now the rule ``'blog/show'`` matches ``/blog/entry/<entry_slug>``.
-    """
-
-    def __init__(self, path: str, rules: t.Iterable[RuleFactory]) -> None:
-        self.path = path.rstrip("/")
-        self.rules = rules
-
-    def get_rules(self, map: Map) -> t.Iterator[Rule]:
-        for rulefactory in self.rules:
-            for rule in rulefactory.get_rules(map):
-                rule = rule.empty()
-                rule.rule = self.path + rule.rule
-                yield rule
-
-
-class EndpointPrefix(RuleFactory):
-    """Prefixes all endpoints (which must be strings for this factory) with
-    another string. This can be useful for sub applications::
-
-        url_map = Map([
-            Rule('/', endpoint='index'),
-            EndpointPrefix('blog/', [Submount('/blog', [
-                Rule('/', endpoint='index'),
-                Rule('/entry/<entry_slug>', endpoint='show')
-            ])])
-        ])
-    """
-
-    def __init__(self, prefix: str, rules: t.Iterable[RuleFactory]) -> None:
-        self.prefix = prefix
-        self.rules = rules
-
-    def get_rules(self, map: Map) -> t.Iterator[Rule]:
-        for rulefactory in self.rules:
-            for rule in rulefactory.get_rules(map):
-                rule = rule.empty()
-                rule.endpoint = self.prefix + rule.endpoint
-                yield rule
-
-
-class RuleTemplate:
-    """Returns copies of the rules wrapped and expands string templates in
-    the endpoint, rule, defaults or subdomain sections.
-
-    Here a small example for such a rule template::
-
-        from werkzeug.routing import Map, Rule, RuleTemplate
-
-        resource = RuleTemplate([
-            Rule('/$name/', endpoint='$name.list'),
-            Rule('/$name/<int:id>', endpoint='$name.show')
-        ])
-
-        url_map = Map([resource(name='user'), resource(name='page')])
-
-    When a rule template is called the keyword arguments are used to
-    replace the placeholders in all the string parameters.
-    """
-
-    def __init__(self, rules: t.Iterable[Rule]) -> None:
-        self.rules = list(rules)
-
-    def __call__(self, *args: t.Any, **kwargs: t.Any) -> RuleTemplateFactory:
-        return RuleTemplateFactory(self.rules, dict(*args, **kwargs))
-
-
-class RuleTemplateFactory(RuleFactory):
-    """A factory that fills in template variables into rules.  Used by
-    `RuleTemplate` internally.
-
-    :internal:
-    """
-
-    def __init__(
-        self, rules: t.Iterable[RuleFactory], context: dict[str, t.Any]
-    ) -> None:
-        self.rules = rules
-        self.context = context
-
-    def get_rules(self, map: Map) -> t.Iterator[Rule]:
-        for rulefactory in self.rules:
-            for rule in rulefactory.get_rules(map):
-                new_defaults = subdomain = None
-                if rule.defaults:
-                    new_defaults = {}
-                    for key, value in rule.defaults.items():
-                        if isinstance(value, str):
-                            value = Template(value).substitute(self.context)
-                        new_defaults[key] = value
-                if rule.subdomain is not None:
-                    subdomain = Template(rule.subdomain).substitute(self.context)
-                new_endpoint = rule.endpoint
-                if isinstance(new_endpoint, str):
-                    new_endpoint = Template(new_endpoint).substitute(self.context)
-                yield Rule(
-                    Template(rule.rule).substitute(self.context),
-                    new_defaults,
-                    subdomain,
-                    rule.methods,
-                    rule.build_only,
-                    new_endpoint,
-                    rule.strict_slashes,
-                )
-
-
-def _prefix_names(src: str) -> ast.stmt:
-    """ast parse and prefix names with `.` to avoid collision with user vars"""
-    tree = ast.parse(src).body[0]
-    if isinstance(tree, ast.Expr):
-        tree = tree.value  # type: ignore
-    for node in ast.walk(tree):
-        if isinstance(node, ast.Name):
-            node.id = f".{node.id}"
-    return tree
-
-
-_CALL_CONVERTER_CODE_FMT = "self._converters[{elem!r}].to_url()"
-_IF_KWARGS_URL_ENCODE_CODE = """\
-if kwargs:
-    params = self._encode_query_vars(kwargs)
-    q = "?" if params else ""
-else:
-    q = params = ""
-"""
-_IF_KWARGS_URL_ENCODE_AST = _prefix_names(_IF_KWARGS_URL_ENCODE_CODE)
-_URL_ENCODE_AST_NAMES = (_prefix_names("q"), _prefix_names("params"))
-
-
-class Rule(RuleFactory):
-    """A Rule represents one URL pattern.  There are some options for `Rule`
-    that change the way it behaves and are passed to the `Rule` constructor.
-    Note that besides the rule-string all arguments *must* be keyword arguments
-    in order to not break the application on Werkzeug upgrades.
-
-    `string`
-        Rule strings basically are just normal URL paths with placeholders in
-        the format ``<converter(arguments):name>`` where the converter and the
-        arguments are optional.  If no converter is defined the `default`
-        converter is used which means `string` in the normal configuration.
-
-        URL rules that end with a slash are branch URLs, others are leaves.
-        If you have `strict_slashes` enabled (which is the default), all
-        branch URLs that are matched without a trailing slash will trigger a
-        redirect to the same URL with the missing slash appended.
-
-        The converters are defined on the `Map`.
-
-    `endpoint`
-        The endpoint for this rule. This can be anything. A reference to a
-        function, a string, a number etc.  The preferred way is using a string
-        because the endpoint is used for URL generation.
-
-    `defaults`
-        An optional dict with defaults for other rules with the same endpoint.
-        This is a bit tricky but useful if you want to have unique URLs::
-
-            url_map = Map([
-                Rule('/all/', defaults={'page': 1}, endpoint='all_entries'),
-                Rule('/all/page/<int:page>', endpoint='all_entries')
-            ])
-
-        If a user now visits ``http://example.com/all/page/1`` they will be
-        redirected to ``http://example.com/all/``.  If `redirect_defaults` is
-        disabled on the `Map` instance this will only affect the URL
-        generation.
-
-    `subdomain`
-        The subdomain rule string for this rule. If not specified the rule
-        only matches for the `default_subdomain` of the map.  If the map is
-        not bound to a subdomain this feature is disabled.
-
-        Can be useful if you want to have user profiles on different subdomains
-        and all subdomains are forwarded to your application::
-
-            url_map = Map([
-                Rule('/', subdomain='<username>', endpoint='user/homepage'),
-                Rule('/stats', subdomain='<username>', endpoint='user/stats')
-            ])
-
-    `methods`
-        A sequence of http methods this rule applies to.  If not specified, all
-        methods are allowed. For example this can be useful if you want different
-        endpoints for `POST` and `GET`.  If methods are defined and the path
-        matches but the method matched against is not in this list or in the
-        list of another rule for that path the error raised is of the type
-        `MethodNotAllowed` rather than `NotFound`.  If `GET` is present in the
-        list of methods and `HEAD` is not, `HEAD` is added automatically.
-
-    `strict_slashes`
-        Override the `Map` setting for `strict_slashes` only for this rule. If
-        not specified the `Map` setting is used.
-
-    `merge_slashes`
-        Override :attr:`Map.merge_slashes` for this rule.
-
-    `build_only`
-        Set this to True and the rule will never match but will create a URL
-        that can be build. This is useful if you have resources on a subdomain
-        or folder that are not handled by the WSGI application (like static data)
-
-    `redirect_to`
-        If given this must be either a string or callable.  In case of a
-        callable it's called with the url adapter that triggered the match and
-        the values of the URL as keyword arguments and has to return the target
-        for the redirect, otherwise it has to be a string with placeholders in
-        rule syntax::
-
-            def foo_with_slug(adapter, id):
-                # ask the database for the slug for the old id.  this of
-                # course has nothing to do with werkzeug.
-                return f'foo/{Foo.get_slug_for_id(id)}'
-
-            url_map = Map([
-                Rule('/foo/<slug>', endpoint='foo'),
-                Rule('/some/old/url/<slug>', redirect_to='foo/<slug>'),
-                Rule('/other/old/url/<int:id>', redirect_to=foo_with_slug)
-            ])
-
-        When the rule is matched the routing system will raise a
-        `RequestRedirect` exception with the target for the redirect.
-
-        Keep in mind that the URL will be joined against the URL root of the
-        script so don't use a leading slash on the target URL unless you
-        really mean root of that domain.
-
-    `alias`
-        If enabled this rule serves as an alias for another rule with the same
-        endpoint and arguments.
-
-    `host`
-        If provided and the URL map has host matching enabled this can be
-        used to provide a match rule for the whole host.  This also means
-        that the subdomain feature is disabled.
-
-    `websocket`
-        If ``True``, this rule is only matches for WebSocket (``ws://``,
-        ``wss://``) requests. By default, rules will only match for HTTP
-        requests.
-
-    .. versionchanged:: 2.1
-        Percent-encoded newlines (``%0a``), which are decoded by WSGI
-        servers, are considered when routing instead of terminating the
-        match early.
-
-    .. versionadded:: 1.0
-        Added ``websocket``.
-
-    .. versionadded:: 1.0
-        Added ``merge_slashes``.
-
-    .. versionadded:: 0.7
-        Added ``alias`` and ``host``.
-
-    .. versionchanged:: 0.6.1
-       ``HEAD`` is added to ``methods`` if ``GET`` is present.
-    """
-
-    def __init__(
-        self,
-        string: str,
-        defaults: t.Mapping[str, t.Any] | None = None,
-        subdomain: str | None = None,
-        methods: t.Iterable[str] | None = None,
-        build_only: bool = False,
-        endpoint: str | None = None,
-        strict_slashes: bool | None = None,
-        merge_slashes: bool | None = None,
-        redirect_to: str | t.Callable[..., str] | None = None,
-        alias: bool = False,
-        host: str | None = None,
-        websocket: bool = False,
-    ) -> None:
-        if not string.startswith("/"):
-            raise ValueError(f"URL rule '{string}' must start with a slash.")
-
-        self.rule = string
-        self.is_leaf = not string.endswith("/")
-        self.is_branch = string.endswith("/")
-
-        self.map: Map = None  # type: ignore
-        self.strict_slashes = strict_slashes
-        self.merge_slashes = merge_slashes
-        self.subdomain = subdomain
-        self.host = host
-        self.defaults = defaults
-        self.build_only = build_only
-        self.alias = alias
-        self.websocket = websocket
-
-        if methods is not None:
-            if isinstance(methods, str):
-                raise TypeError("'methods' should be a list of strings.")
-
-            methods = {x.upper() for x in methods}
-
-            if "HEAD" not in methods and "GET" in methods:
-                methods.add("HEAD")
-
-            if websocket and methods - {"GET", "HEAD", "OPTIONS"}:
-                raise ValueError(
-                    "WebSocket rules can only use 'GET', 'HEAD', and 'OPTIONS' methods."
-                )
-
-        self.methods = methods
-        self.endpoint: str = endpoint  # type: ignore
-        self.redirect_to = redirect_to
-
-        if defaults:
-            self.arguments = set(map(str, defaults))
-        else:
-            self.arguments = set()
-
-        self._converters: dict[str, BaseConverter] = {}
-        self._trace: list[tuple[bool, str]] = []
-        self._parts: list[RulePart] = []
-
-    def empty(self) -> Rule:
-        """
-        Return an unbound copy of this rule.
-
-        This can be useful if want to reuse an already bound URL for another
-        map.  See ``get_empty_kwargs`` to override what keyword arguments are
-        provided to the new copy.
-        """
-        return type(self)(self.rule, **self.get_empty_kwargs())
-
-    def get_empty_kwargs(self) -> t.Mapping[str, t.Any]:
-        """
-        Provides kwargs for instantiating empty copy with empty()
-
-        Use this method to provide custom keyword arguments to the subclass of
-        ``Rule`` when calling ``some_rule.empty()``.  Helpful when the subclass
-        has custom keyword arguments that are needed at instantiation.
-
-        Must return a ``dict`` that will be provided as kwargs to the new
-        instance of ``Rule``, following the initial ``self.rule`` value which
-        is always provided as the first, required positional argument.
-        """
-        defaults = None
-        if self.defaults:
-            defaults = dict(self.defaults)
-        return dict(
-            defaults=defaults,
-            subdomain=self.subdomain,
-            methods=self.methods,
-            build_only=self.build_only,
-            endpoint=self.endpoint,
-            strict_slashes=self.strict_slashes,
-            redirect_to=self.redirect_to,
-            alias=self.alias,
-            host=self.host,
-        )
-
-    def get_rules(self, map: Map) -> t.Iterator[Rule]:
-        yield self
-
-    def refresh(self) -> None:
-        """Rebinds and refreshes the URL.  Call this if you modified the
-        rule in place.
-
-        :internal:
-        """
-        self.bind(self.map, rebind=True)
-
-    def bind(self, map: Map, rebind: bool = False) -> None:
-        """Bind the url to a map and create a regular expression based on
-        the information from the rule itself and the defaults from the map.
-
-        :internal:
-        """
-        if self.map is not None and not rebind:
-            raise RuntimeError(f"url rule {self!r} already bound to map {self.map!r}")
-        self.map = map
-        if self.strict_slashes is None:
-            self.strict_slashes = map.strict_slashes
-        if self.merge_slashes is None:
-            self.merge_slashes = map.merge_slashes
-        if self.subdomain is None:
-            self.subdomain = map.default_subdomain
-        self.compile()
-
-    def get_converter(
-        self,
-        variable_name: str,
-        converter_name: str,
-        args: t.Tuple,
-        kwargs: t.Mapping[str, t.Any],
-    ) -> BaseConverter:
-        """Looks up the converter for the given parameter.
-
-        .. versionadded:: 0.9
-        """
-        if converter_name not in self.map.converters:
-            raise LookupError(f"the converter {converter_name!r} does not exist")
-        return self.map.converters[converter_name](self.map, *args, **kwargs)
-
-    def _encode_query_vars(self, query_vars: t.Mapping[str, t.Any]) -> str:
-        items: t.Iterable[tuple[str, str]] = iter_multi_items(query_vars)
-
-        if self.map.sort_parameters:
-            items = sorted(items, key=self.map.sort_key)
-
-        return _urlencode(items)
-
-    def _parse_rule(self, rule: str) -> t.Iterable[RulePart]:
-        content = ""
-        static = True
-        argument_weights = []
-        static_weights: list[tuple[int, int]] = []
-        final = False
-        convertor_number = 0
-
-        pos = 0
-        while pos < len(rule):
-            match = _part_re.match(rule, pos)
-            if match is None:
-                raise ValueError(f"malformed url rule: {rule!r}")
-
-            data = match.groupdict()
-            if data["static"] is not None:
-                static_weights.append((len(static_weights), -len(data["static"])))
-                self._trace.append((False, data["static"]))
-                content += data["static"] if static else re.escape(data["static"])
-
-            if data["variable"] is not None:
-                if static:
-                    # Switching content to represent regex, hence the need to escape
-                    content = re.escape(content)
-                static = False
-                c_args, c_kwargs = parse_converter_args(data["arguments"] or "")
-                convobj = self.get_converter(
-                    data["variable"], data["converter"] or "default", c_args, c_kwargs
-                )
-                self._converters[data["variable"]] = convobj
-                self.arguments.add(data["variable"])
-                if not convobj.part_isolating:
-                    final = True
-                content += f"(?P<__werkzeug_{convertor_number}>{convobj.regex})"
-                convertor_number += 1
-                argument_weights.append(convobj.weight)
-                self._trace.append((True, data["variable"]))
-
-            if data["slash"] is not None:
-                self._trace.append((False, "/"))
-                if final:
-                    content += "/"
-                else:
-                    if not static:
-                        content += r"\Z"
-                    weight = Weighting(
-                        -len(static_weights),
-                        static_weights,
-                        -len(argument_weights),
-                        argument_weights,
-                    )
-                    yield RulePart(
-                        content=content,
-                        final=final,
-                        static=static,
-                        suffixed=False,
-                        weight=weight,
-                    )
-                    content = ""
-                    static = True
-                    argument_weights = []
-                    static_weights = []
-                    final = False
-                    convertor_number = 0
-
-            pos = match.end()
-
-        suffixed = False
-        if final and content[-1] == "/":
-            # If a converter is part_isolating=False (matches slashes) and ends with a
-            # slash, augment the regex to support slash redirects.
-            suffixed = True
-            content = content[:-1] + "(?<!/)(/?)"
-        if not static:
-            content += r"\Z"
-        weight = Weighting(
-            -len(static_weights),
-            static_weights,
-            -len(argument_weights),
-            argument_weights,
-        )
-        yield RulePart(
-            content=content,
-            final=final,
-            static=static,
-            suffixed=suffixed,
-            weight=weight,
-        )
-        if suffixed:
-            yield RulePart(
-                content="", final=False, static=True, suffixed=False, weight=weight
-            )
-
-    def compile(self) -> None:
-        """Compiles the regular expression and stores it."""
-        assert self.map is not None, "rule not bound"
-
-        if self.map.host_matching:
-            domain_rule = self.host or ""
-        else:
-            domain_rule = self.subdomain or ""
-        self._parts = []
-        self._trace = []
-        self._converters = {}
-        if domain_rule == "":
-            self._parts = [
-                RulePart(
-                    content="",
-                    final=False,
-                    static=True,
-                    suffixed=False,
-                    weight=Weighting(0, [], 0, []),
-                )
-            ]
-        else:
-            self._parts.extend(self._parse_rule(domain_rule))
-        self._trace.append((False, "|"))
-        rule = self.rule
-        if self.merge_slashes:
-            rule = re.sub("/{2,}?", "/", self.rule)
-        self._parts.extend(self._parse_rule(rule))
-
-        self._build: t.Callable[..., tuple[str, str]]
-        self._build = self._compile_builder(False).__get__(self, None)
-        self._build_unknown: t.Callable[..., tuple[str, str]]
-        self._build_unknown = self._compile_builder(True).__get__(self, None)
-
-    @staticmethod
-    def _get_func_code(code: CodeType, name: str) -> t.Callable[..., tuple[str, str]]:
-        globs: dict[str, t.Any] = {}
-        locs: dict[str, t.Any] = {}
-        exec(code, globs, locs)
-        return locs[name]  # type: ignore
-
-    def _compile_builder(
-        self, append_unknown: bool = True
-    ) -> t.Callable[..., tuple[str, str]]:
-        defaults = self.defaults or {}
-        dom_ops: list[tuple[bool, str]] = []
-        url_ops: list[tuple[bool, str]] = []
-
-        opl = dom_ops
-        for is_dynamic, data in self._trace:
-            if data == "|" and opl is dom_ops:
-                opl = url_ops
-                continue
-            # this seems like a silly case to ever come up but:
-            # if a default is given for a value that appears in the rule,
-            # resolve it to a constant ahead of time
-            if is_dynamic and data in defaults:
-                data = self._converters[data].to_url(defaults[data])
-                opl.append((False, data))
-            elif not is_dynamic:
-                # safe = https://url.spec.whatwg.org/#url-path-segment-string
-                opl.append((False, quote(data, safe="!$&'()*+,/:;=@")))
-            else:
-                opl.append((True, data))
-
-        def _convert(elem: str) -> ast.stmt:
-            ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem))
-            ret.args = [ast.Name(str(elem), ast.Load())]  # type: ignore  # str for py2
-            return ret
-
-        def _parts(ops: list[tuple[bool, str]]) -> list[ast.AST]:
-            parts = [
-                _convert(elem) if is_dynamic else ast.Constant(elem)
-                for is_dynamic, elem in ops
-            ]
-            parts = parts or [ast.Constant("")]
-            # constant fold
-            ret = [parts[0]]
-            for p in parts[1:]:
-                if isinstance(p, ast.Constant) and isinstance(ret[-1], ast.Constant):
-                    ret[-1] = ast.Constant(ret[-1].value + p.value)
-                else:
-                    ret.append(p)
-            return ret
-
-        dom_parts = _parts(dom_ops)
-        url_parts = _parts(url_ops)
-        if not append_unknown:
-            body = []
-        else:
-            body = [_IF_KWARGS_URL_ENCODE_AST]
-            url_parts.extend(_URL_ENCODE_AST_NAMES)
-
-        def _join(parts: list[ast.AST]) -> ast.AST:
-            if len(parts) == 1:  # shortcut
-                return parts[0]
-            return ast.JoinedStr(parts)
-
-        body.append(
-            ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load()))
-        )
-
-        pargs = [
-            elem
-            for is_dynamic, elem in dom_ops + url_ops
-            if is_dynamic and elem not in defaults
-        ]
-        kargs = [str(k) for k in defaults]
-
-        func_ast: ast.FunctionDef = _prefix_names("def _(): pass")  # type: ignore
-        func_ast.name = f"<builder:{self.rule!r}>"
-        func_ast.args.args.append(ast.arg(".self", None))
-        for arg in pargs + kargs:
-            func_ast.args.args.append(ast.arg(arg, None))
-        func_ast.args.kwarg = ast.arg(".kwargs", None)
-        for _ in kargs:
-            func_ast.args.defaults.append(ast.Constant(""))
-        func_ast.body = body
-
-        # Use `ast.parse` instead of `ast.Module` for better portability, since the
-        # signature of `ast.Module` can change.
-        module = ast.parse("")
-        module.body = [func_ast]
-
-        # mark everything as on line 1, offset 0
-        # less error-prone than `ast.fix_missing_locations`
-        # bad line numbers cause an assert to fail in debug builds
-        for node in ast.walk(module):
-            if "lineno" in node._attributes:
-                node.lineno = 1
-            if "end_lineno" in node._attributes:
-                node.end_lineno = node.lineno
-            if "col_offset" in node._attributes:
-                node.col_offset = 0
-            if "end_col_offset" in node._attributes:
-                node.end_col_offset = node.col_offset
-
-        code = compile(module, "<werkzeug routing>", "exec")
-        return self._get_func_code(code, func_ast.name)
-
-    def build(
-        self, values: t.Mapping[str, t.Any], append_unknown: bool = True
-    ) -> tuple[str, str] | None:
-        """Assembles the relative url for that rule and the subdomain.
-        If building doesn't work for some reasons `None` is returned.
-
-        :internal:
-        """
-        try:
-            if append_unknown:
-                return self._build_unknown(**values)
-            else:
-                return self._build(**values)
-        except ValidationError:
-            return None
-
-    def provides_defaults_for(self, rule: Rule) -> bool:
-        """Check if this rule has defaults for a given rule.
-
-        :internal:
-        """
-        return bool(
-            not self.build_only
-            and self.defaults
-            and self.endpoint == rule.endpoint
-            and self != rule
-            and self.arguments == rule.arguments
-        )
-
-    def suitable_for(
-        self, values: t.Mapping[str, t.Any], method: str | None = None
-    ) -> bool:
-        """Check if the dict of values has enough data for url generation.
-
-        :internal:
-        """
-        # if a method was given explicitly and that method is not supported
-        # by this rule, this rule is not suitable.
-        if (
-            method is not None
-            and self.methods is not None
-            and method not in self.methods
-        ):
-            return False
-
-        defaults = self.defaults or ()
-
-        # all arguments required must be either in the defaults dict or
-        # the value dictionary otherwise it's not suitable
-        for key in self.arguments:
-            if key not in defaults and key not in values:
-                return False
-
-        # in case defaults are given we ensure that either the value was
-        # skipped or the value is the same as the default value.
-        if defaults:
-            for key, value in defaults.items():
-                if key in values and value != values[key]:
-                    return False
-
-        return True
-
-    def build_compare_key(self) -> tuple[int, int, int]:
-        """The build compare key for sorting.
-
-        :internal:
-        """
-        return (1 if self.alias else 0, -len(self.arguments), -len(self.defaults or ()))
-
-    def __eq__(self, other: object) -> bool:
-        return isinstance(other, type(self)) and self._trace == other._trace
-
-    __hash__ = None  # type: ignore
-
-    def __str__(self) -> str:
-        return self.rule
-
-    def __repr__(self) -> str:
-        if self.map is None:
-            return f"<{type(self).__name__} (unbound)>"
-        parts = []
-        for is_dynamic, data in self._trace:
-            if is_dynamic:
-                parts.append(f"<{data}>")
-            else:
-                parts.append(data)
-        parts = "".join(parts).lstrip("|")
-        methods = f" ({', '.join(self.methods)})" if self.methods is not None else ""
-        return f"<{type(self).__name__} {parts!r}{methods} -> {self.endpoint}>"