Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/starlette/convertors.py: 61%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

51 statements  

1from __future__ import annotations 

2 

3import math 

4import typing 

5import uuid 

6 

7T = typing.TypeVar("T") 

8 

9 

10class Convertor(typing.Generic[T]): 

11 regex: typing.ClassVar[str] = "" 

12 

13 def convert(self, value: str) -> T: 

14 raise NotImplementedError() # pragma: no cover 

15 

16 def to_string(self, value: T) -> str: 

17 raise NotImplementedError() # pragma: no cover 

18 

19 

20class StringConvertor(Convertor[str]): 

21 regex = "[^/]+" 

22 

23 def convert(self, value: str) -> str: 

24 return value 

25 

26 def to_string(self, value: str) -> str: 

27 value = str(value) 

28 assert "/" not in value, "May not contain path separators" 

29 assert value, "Must not be empty" 

30 return value 

31 

32 

33class PathConvertor(Convertor[str]): 

34 regex = ".*" 

35 

36 def convert(self, value: str) -> str: 

37 return str(value) 

38 

39 def to_string(self, value: str) -> str: 

40 return str(value) 

41 

42 

43class IntegerConvertor(Convertor[int]): 

44 regex = "[0-9]+" 

45 

46 def convert(self, value: str) -> int: 

47 return int(value) 

48 

49 def to_string(self, value: int) -> str: 

50 value = int(value) 

51 assert value >= 0, "Negative integers are not supported" 

52 return str(value) 

53 

54 

55class FloatConvertor(Convertor[float]): 

56 regex = r"[0-9]+(\.[0-9]+)?" 

57 

58 def convert(self, value: str) -> float: 

59 return float(value) 

60 

61 def to_string(self, value: float) -> str: 

62 value = float(value) 

63 assert value >= 0.0, "Negative floats are not supported" 

64 assert not math.isnan(value), "NaN values are not supported" 

65 assert not math.isinf(value), "Infinite values are not supported" 

66 return ("%0.20f" % value).rstrip("0").rstrip(".") 

67 

68 

69class UUIDConvertor(Convertor[uuid.UUID]): 

70 regex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" 

71 

72 def convert(self, value: str) -> uuid.UUID: 

73 return uuid.UUID(value) 

74 

75 def to_string(self, value: uuid.UUID) -> str: 

76 return str(value) 

77 

78 

79CONVERTOR_TYPES: dict[str, Convertor[typing.Any]] = { 

80 "str": StringConvertor(), 

81 "path": PathConvertor(), 

82 "int": IntegerConvertor(), 

83 "float": FloatConvertor(), 

84 "uuid": UUIDConvertor(), 

85} 

86 

87 

88def register_url_convertor(key: str, convertor: Convertor[typing.Any]) -> None: 

89 CONVERTOR_TYPES[key] = convertor