Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/azure/core/utils/_utils.py: 32%

71 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-07 06:33 +0000

1# coding=utf-8 

2# -------------------------------------------------------------------------- 

3# Copyright (c) Microsoft Corporation. All rights reserved. 

4# Licensed under the MIT License. See License.txt in the project root for 

5# license information. 

6# -------------------------------------------------------------------------- 

7import datetime 

8from typing import ( 

9 Any, 

10 Iterable, 

11 Iterator, 

12 Mapping, 

13 MutableMapping, 

14 Optional, 

15 Tuple, 

16 Union, 

17 Dict, 

18) 

19from datetime import timezone 

20 

21TZ_UTC = timezone.utc 

22 

23 

24class _FixedOffset(datetime.tzinfo): 

25 """Fixed offset in minutes east from UTC. 

26 

27 Copy/pasted from Python doc 

28 

29 :param int offset: offset in minutes 

30 """ 

31 

32 def __init__(self, offset): 

33 self.__offset = datetime.timedelta(minutes=offset) 

34 

35 def utcoffset(self, dt): 

36 return self.__offset 

37 

38 def tzname(self, dt): 

39 return str(self.__offset.total_seconds() / 3600) 

40 

41 def __repr__(self): 

42 return "<FixedOffset {}>".format(self.tzname(None)) 

43 

44 def dst(self, dt): 

45 return datetime.timedelta(0) 

46 

47 

48def _convert_to_isoformat(date_time): 

49 """Deserialize a date in RFC 3339 format to datetime object. 

50 Check https://tools.ietf.org/html/rfc3339#section-5.8 for examples. 

51 

52 :param str date_time: The date in RFC 3339 format. 

53 """ 

54 if not date_time: 

55 return None 

56 if date_time[-1] == "Z": 

57 delta = 0 

58 timestamp = date_time[:-1] 

59 else: 

60 timestamp = date_time[:-6] 

61 sign, offset = date_time[-6], date_time[-5:] 

62 delta = int(sign + offset[:1]) * 60 + int(sign + offset[-2:]) 

63 

64 check_decimal = timestamp.split(".") 

65 if len(check_decimal) > 1: 

66 decimal_str = "" 

67 for digit in check_decimal[1]: 

68 if digit.isdigit(): 

69 decimal_str += digit 

70 else: 

71 break 

72 if len(decimal_str) > 6: 

73 timestamp = timestamp.replace(decimal_str, decimal_str[0:6]) 

74 

75 if delta == 0: 

76 tzinfo = TZ_UTC 

77 else: 

78 tzinfo = timezone(datetime.timedelta(minutes=delta)) 

79 

80 try: 

81 deserialized = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f") 

82 except ValueError: 

83 deserialized = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S") 

84 

85 deserialized = deserialized.replace(tzinfo=tzinfo) 

86 return deserialized 

87 

88 

89def case_insensitive_dict( 

90 *args: Optional[Union[Mapping[str, Any], Iterable[Tuple[str, Any]]]], **kwargs: Any 

91) -> MutableMapping[str, Any]: 

92 """Return a case-insensitive mutable mapping from an inputted mapping structure. 

93 

94 :param args: The positional arguments to pass to the dict. 

95 :type args: Mapping[str, Any] or Iterable[Tuple[str, Any] 

96 :return: A case-insensitive mutable mapping object. 

97 :rtype: ~collections.abc.MutableMapping 

98 """ 

99 return CaseInsensitiveDict(*args, **kwargs) 

100 

101 

102class CaseInsensitiveDict(MutableMapping[str, Any]): 

103 """ 

104 NOTE: This implementation is heavily inspired from the case insensitive dictionary from the requests library. 

105 Thank you !! 

106 Case insensitive dictionary implementation. 

107 The keys are expected to be strings and will be stored in lower case. 

108 case_insensitive_dict = CaseInsensitiveDict() 

109 case_insensitive_dict['Key'] = 'some_value' 

110 case_insensitive_dict['key'] == 'some_value' #True 

111 

112 :param data: Initial data to store in the dictionary. 

113 :type data: Mapping[str, Any] or Iterable[Tuple[str, Any]] 

114 """ 

115 

116 def __init__( 

117 self, data: Optional[Union[Mapping[str, Any], Iterable[Tuple[str, Any]]]] = None, **kwargs: Any 

118 ) -> None: 

119 self._store: Dict[str, Any] = {} 

120 if data is None: 

121 data = {} 

122 

123 self.update(data, **kwargs) 

124 

125 def copy(self) -> "CaseInsensitiveDict": 

126 return CaseInsensitiveDict(self._store.values()) 

127 

128 def __setitem__(self, key: str, value: Any) -> None: 

129 """Set the `key` to `value`. 

130 

131 The original key will be stored with the value 

132 

133 :param str key: The key to set. 

134 :param value: The value to set the key to. 

135 :type value: any 

136 """ 

137 self._store[key.lower()] = (key, value) 

138 

139 def __getitem__(self, key: str) -> Any: 

140 return self._store[key.lower()][1] 

141 

142 def __delitem__(self, key: str) -> None: 

143 del self._store[key.lower()] 

144 

145 def __iter__(self) -> Iterator[str]: 

146 return (key for key, _ in self._store.values()) 

147 

148 def __len__(self) -> int: 

149 return len(self._store) 

150 

151 def lowerkey_items(self) -> Iterator[Tuple[str, Any]]: 

152 return ((lower_case_key, pair[1]) for lower_case_key, pair in self._store.items()) 

153 

154 def __eq__(self, other: Any) -> bool: 

155 if isinstance(other, Mapping): 

156 other = CaseInsensitiveDict(other) 

157 else: 

158 return False 

159 

160 return dict(self.lowerkey_items()) == dict(other.lowerkey_items()) 

161 

162 def __repr__(self) -> str: 

163 return str(dict(self.items()))