Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

90 lignes
2.3 KiB

  1. from __future__ import annotations
  2. import math
  3. import uuid
  4. from typing import Any, ClassVar, Generic, TypeVar
  5. T = TypeVar("T")
  6. class Convertor(Generic[T]):
  7. regex: ClassVar[str] = ""
  8. def convert(self, value: str) -> T:
  9. raise NotImplementedError() # pragma: no cover
  10. def to_string(self, value: T) -> str:
  11. raise NotImplementedError() # pragma: no cover
  12. class StringConvertor(Convertor[str]):
  13. regex = "[^/]+"
  14. def convert(self, value: str) -> str:
  15. return value
  16. def to_string(self, value: str) -> str:
  17. value = str(value)
  18. assert "/" not in value, "May not contain path separators"
  19. assert value, "Must not be empty"
  20. return value
  21. class PathConvertor(Convertor[str]):
  22. regex = ".*"
  23. def convert(self, value: str) -> str:
  24. return str(value)
  25. def to_string(self, value: str) -> str:
  26. return str(value)
  27. class IntegerConvertor(Convertor[int]):
  28. regex = "[0-9]+"
  29. def convert(self, value: str) -> int:
  30. return int(value)
  31. def to_string(self, value: int) -> str:
  32. value = int(value)
  33. assert value >= 0, "Negative integers are not supported"
  34. return str(value)
  35. class FloatConvertor(Convertor[float]):
  36. regex = r"[0-9]+(\.[0-9]+)?"
  37. def convert(self, value: str) -> float:
  38. return float(value)
  39. def to_string(self, value: float) -> str:
  40. value = float(value)
  41. assert value >= 0.0, "Negative floats are not supported"
  42. assert not math.isnan(value), "NaN values are not supported"
  43. assert not math.isinf(value), "Infinite values are not supported"
  44. return ("%0.20f" % value).rstrip("0").rstrip(".")
  45. class UUIDConvertor(Convertor[uuid.UUID]):
  46. 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}"
  47. def convert(self, value: str) -> uuid.UUID:
  48. return uuid.UUID(value)
  49. def to_string(self, value: uuid.UUID) -> str:
  50. return str(value)
  51. CONVERTOR_TYPES: dict[str, Convertor[Any]] = {
  52. "str": StringConvertor(),
  53. "path": PathConvertor(),
  54. "int": IntegerConvertor(),
  55. "float": FloatConvertor(),
  56. "uuid": UUIDConvertor(),
  57. }
  58. def register_url_convertor(key: str, convertor: Convertor[Any]) -> None:
  59. CONVERTOR_TYPES[key] = convertor