|
- from __future__ import annotations
-
- import math
- import uuid
- from typing import Any, ClassVar, Generic, TypeVar
-
- T = TypeVar("T")
-
-
- class Convertor(Generic[T]):
- regex: ClassVar[str] = ""
-
- def convert(self, value: str) -> T:
- raise NotImplementedError() # pragma: no cover
-
- def to_string(self, value: T) -> str:
- raise NotImplementedError() # pragma: no cover
-
-
- class StringConvertor(Convertor[str]):
- regex = "[^/]+"
-
- def convert(self, value: str) -> str:
- return value
-
- def to_string(self, value: str) -> str:
- value = str(value)
- assert "/" not in value, "May not contain path separators"
- assert value, "Must not be empty"
- return value
-
-
- class PathConvertor(Convertor[str]):
- regex = ".*"
-
- def convert(self, value: str) -> str:
- return str(value)
-
- def to_string(self, value: str) -> str:
- return str(value)
-
-
- class IntegerConvertor(Convertor[int]):
- regex = "[0-9]+"
-
- def convert(self, value: str) -> int:
- return int(value)
-
- def to_string(self, value: int) -> str:
- value = int(value)
- assert value >= 0, "Negative integers are not supported"
- return str(value)
-
-
- class FloatConvertor(Convertor[float]):
- regex = r"[0-9]+(\.[0-9]+)?"
-
- def convert(self, value: str) -> float:
- return float(value)
-
- def to_string(self, value: float) -> str:
- value = float(value)
- assert value >= 0.0, "Negative floats are not supported"
- assert not math.isnan(value), "NaN values are not supported"
- assert not math.isinf(value), "Infinite values are not supported"
- return ("%0.20f" % value).rstrip("0").rstrip(".")
-
-
- class UUIDConvertor(Convertor[uuid.UUID]):
- regex = "[0-9a-fA-F]{8}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{4}-?[0-9a-fA-F]{12}"
-
- def convert(self, value: str) -> uuid.UUID:
- return uuid.UUID(value)
-
- def to_string(self, value: uuid.UUID) -> str:
- return str(value)
-
-
- CONVERTOR_TYPES: dict[str, Convertor[Any]] = {
- "str": StringConvertor(),
- "path": PathConvertor(),
- "int": IntegerConvertor(),
- "float": FloatConvertor(),
- "uuid": UUIDConvertor(),
- }
-
-
- def register_url_convertor(key: str, convertor: Convertor[Any]) -> None:
- CONVERTOR_TYPES[key] = convertor
|