Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/uri_template/variable.py: 25%

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

60 statements  

1"""Variable class for URITemplate.""" 

2 

3from __future__ import annotations 

4 

5from .charset import Charset 

6 

7 

8class VariableInvalidError(Exception): 

9 """Exception thrown for invalid variables.""" 

10 

11 variable: str 

12 

13 def __init__(self, variable: str) -> None: 

14 self.variable = variable 

15 

16 def __str__(self) -> str: 

17 """Convert to string.""" 

18 return 'Bad variable: ' + self.variable 

19 

20 

21class Variable: 

22 """ 

23 A template variable. 

24 

25 https://tools.ietf.org/html/rfc6570#section-2.3 

26 """ 

27 

28 name: str 

29 key: str 

30 max_length: int 

31 explode: bool 

32 array: bool 

33 default: (str | None) 

34 

35 def __init__(self, var_spec: str) -> None: 

36 self.name = '' 

37 self.key = '' 

38 self.max_length = 0 

39 self.explode = False 

40 self.array = False 

41 self.default = None 

42 

43 if (var_spec[0:1] not in Charset.VAR_START): 

44 raise VariableInvalidError(var_spec) 

45 

46 if ('=' in var_spec): 

47 var_spec, self.default = var_spec.split('=', 1) 

48 

49 if (':' in var_spec): 

50 var_spec, max_length = var_spec.split(':', 1) 

51 if ((0 < len(max_length)) and (len(max_length) < 4)): 

52 for digit in max_length: 

53 if (digit not in Charset.DIGIT): 

54 raise VariableInvalidError(var_spec + ':' + max_length) 

55 self.max_length = int(max_length) 

56 if (not self.max_length): 

57 raise VariableInvalidError(var_spec + ':' + max_length) 

58 else: 

59 raise VariableInvalidError(var_spec + ':' + max_length) 

60 elif ('*' == var_spec[-1]): 

61 var_spec = var_spec[:-1] 

62 self.explode = True 

63 elif ('[]' == var_spec[-2:]): 

64 var_spec = var_spec[:-2] 

65 self.array = True 

66 self.explode = True 

67 

68 index = 0 

69 while (index < len(var_spec)): 

70 codepoint = var_spec[index] 

71 if (('%' == codepoint) 

72 and ((index + 2) < len(var_spec)) 

73 and (var_spec[index + 1] in Charset.HEX_DIGIT) 

74 and (var_spec[index + 2] in Charset.HEX_DIGIT)): 

75 self.key += var_spec[index:index + 3] 

76 index += 2 

77 elif (codepoint in Charset.VAR_CHAR): 

78 self.key += codepoint 

79 elif ('/' == codepoint): 

80 self.name = self.key 

81 self.key = '' 

82 else: 

83 raise VariableInvalidError(var_spec + ((':' + str(self.max_length)) if (self.max_length) else '') 

84 + ('[]' if (self.array) else ('*' if (self.explode) else ''))) 

85 index += 1 

86 

87 self.name = (self.name or self.key) 

88 self.key = (self.key or self.name) 

89 

90 def __str__(self) -> str: 

91 """Convert to string.""" 

92 return (self.name + (f'/{self.key}' if (self.key and (self.key != self.name)) else '') 

93 + (f':{self.max_length}' if (self.max_length) else '') 

94 + ('*' if (self.explode and not self.array) else '') + ('[]' if (self.array) else '') 

95 + (f'={self.default}' if (self.default is not None) else ''))