]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/werkzeug/routing/converters.py
1 from __future__
import annotations
6 from urllib
.parse
import quote
12 class ValidationError(ValueError):
13 """Validation error. If a rule converter raises this exception the rule
14 does not match the current URL and the next URL is tried.
19 """Base class for all converters.
21 .. versionchanged:: 2.3
22 ``part_isolating`` defaults to ``False`` if ``regex`` contains a ``/``.
29 def __init_subclass__(cls
, **kwargs
: t
.Any
) -> None:
30 super().__init
_subclass
__(**kwargs
)
32 # If the converter isn't inheriting its regex, disable part_isolating by default
33 # if the regex contains a / character.
34 if "regex" in cls
.__dict
__ and "part_isolating" not in cls
.__dict
__:
35 cls
.part_isolating
= "/" not in cls
.regex
37 def __init__(self
, map: Map
, *args
: t
.Any
, **kwargs
: t
.Any
) -> None:
40 def to_python(self
, value
: str) -> t
.Any
:
43 def to_url(self
, value
: t
.Any
) -> str:
44 # safe = https://url.spec.whatwg.org/#url-path-segment-string
45 return quote(str(value
), safe
="!$&'()*+,/:;=@")
48 class UnicodeConverter(BaseConverter
):
49 """This converter is the default converter and accepts any string but
50 only one path segment. Thus the string can not include a slash.
52 This is the default validator.
56 Rule('/pages/<page>'),
57 Rule('/<string(length=2):lang_code>')
59 :param map: the :class:`Map`.
60 :param minlength: the minimum length of the string. Must be greater
62 :param maxlength: the maximum length of the string.
63 :param length: the exact length of the string.
70 maxlength
: int |
None = None,
71 length
: int |
None = None,
74 if length
is not None:
75 length_regex
= f
"{{{int(length)}}}"
80 maxlength_value
= str(int(maxlength
))
81 length_regex
= f
"{{{int(minlength)},{maxlength_value}}}"
82 self
.regex
= f
"[^/]{length_regex}"
85 class AnyConverter(BaseConverter
):
86 """Matches one of the items provided. Items can either be Python
87 identifiers or strings::
89 Rule('/<any(about, help, imprint, class, "foo,bar"):page_name>')
91 :param map: the :class:`Map`.
92 :param items: this function accepts the possible items as positional
95 .. versionchanged:: 2.2
96 Value is validated when building a URL.
99 def __init__(self
, map: Map
, *items
: str) -> None:
100 super().__init
__(map)
101 self
.items
= set(items
)
102 self
.regex
= f
"(?:{'|'.join([re.escape(x) for x in items])})"
104 def to_url(self
, value
: t
.Any
) -> str:
105 if value
in self
.items
:
108 valid_values
= ", ".join(f
"'{item}'" for item
in sorted(self
.items
))
109 raise ValueError(f
"'{value}' is not one of {valid_values}")
112 class PathConverter(BaseConverter
):
113 """Like the default :class:`UnicodeConverter`, but it also matches
114 slashes. This is useful for wikis and similar applications::
116 Rule('/<path:wikipage>')
117 Rule('/<path:wikipage>/edit')
119 :param map: the :class:`Map`.
122 part_isolating
= False
127 class NumberConverter(BaseConverter
):
128 """Baseclass for `IntegerConverter` and `FloatConverter`.
134 num_convert
: t
.Callable
= int
139 fixed_digits
: int = 0,
140 min: int |
None = None,
141 max: int |
None = None,
142 signed
: bool = False,
145 self
.regex
= self
.signed_regex
146 super().__init
__(map)
147 self
.fixed_digits
= fixed_digits
152 def to_python(self
, value
: str) -> t
.Any
:
153 if self
.fixed_digits
and len(value
) != self
.fixed_digits
:
154 raise ValidationError()
155 value
= self
.num_convert(value
)
156 if (self
.min is not None and value
< self
.min) or (
157 self
.max is not None and value
> self
.max
159 raise ValidationError()
162 def to_url(self
, value
: t
.Any
) -> str:
163 value
= str(self
.num_convert(value
))
164 if self
.fixed_digits
:
165 value
= value
.zfill(self
.fixed_digits
)
169 def signed_regex(self
) -> str:
170 return f
"-?{self.regex}"
173 class IntegerConverter(NumberConverter
):
174 """This converter only accepts integer values::
176 Rule("/page/<int:page>")
178 By default it only accepts unsigned, positive values. The ``signed``
179 parameter will enable signed, negative values. ::
181 Rule("/page/<int(signed=True):page>")
183 :param map: The :class:`Map`.
184 :param fixed_digits: The number of fixed digits in the URL. If you
185 set this to ``4`` for example, the rule will only match if the
186 URL looks like ``/0001/``. The default is variable length.
187 :param min: The minimal value.
188 :param max: The maximal value.
189 :param signed: Allow signed (negative) values.
191 .. versionadded:: 0.15
192 The ``signed`` parameter.
198 class FloatConverter(NumberConverter
):
199 """This converter only accepts floating point values::
201 Rule("/probability/<float:probability>")
203 By default it only accepts unsigned, positive values. The ``signed``
204 parameter will enable signed, negative values. ::
206 Rule("/offset/<float(signed=True):offset>")
208 :param map: The :class:`Map`.
209 :param min: The minimal value.
210 :param max: The maximal value.
211 :param signed: Allow signed (negative) values.
213 .. versionadded:: 0.15
214 The ``signed`` parameter.
223 min: float |
None = None,
224 max: float |
None = None,
225 signed
: bool = False,
227 super().__init
__(map, min=min, max=max, signed
=signed
) # type: ignore
230 class UUIDConverter(BaseConverter
):
231 """This converter only accepts UUID strings::
233 Rule('/object/<uuid:identifier>')
235 .. versionadded:: 0.10
237 :param map: the :class:`Map`.
241 r
"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-"
242 r
"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"
245 def to_python(self
, value
: str) -> uuid
.UUID
:
246 return uuid
.UUID(value
)
248 def to_url(self
, value
: uuid
.UUID
) -> str:
252 #: the default converter mapping for the map.
253 DEFAULT_CONVERTERS
: t
.Mapping
[str, type[BaseConverter
]] = {
254 "default": UnicodeConverter
,
255 "string": UnicodeConverter
,
257 "path": PathConverter
,
258 "int": IntegerConverter
,
259 "float": FloatConverter
,
260 "uuid": UUIDConverter
,