Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/pyarrow/util.py: 30%

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

125 statements  

1# Licensed to the Apache Software Foundation (ASF) under one 

2# or more contributor license agreements. See the NOTICE file 

3# distributed with this work for additional information 

4# regarding copyright ownership. The ASF licenses this file 

5# to you under the Apache License, Version 2.0 (the 

6# "License"); you may not use this file except in compliance 

7# with the License. You may obtain a copy of the License at 

8# 

9# http://www.apache.org/licenses/LICENSE-2.0 

10# 

11# Unless required by applicable law or agreed to in writing, 

12# software distributed under the License is distributed on an 

13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 

14# KIND, either express or implied. See the License for the 

15# specific language governing permissions and limitations 

16# under the License. 

17 

18# Miscellaneous utility code 

19 

20import os 

21import contextlib 

22import functools 

23import gc 

24import socket 

25import sys 

26import textwrap 

27import types 

28import warnings 

29 

30 

31_DEPR_MSG = ( 

32 "pyarrow.{} is deprecated as of {}, please use pyarrow.{} instead." 

33) 

34 

35 

36def doc(*docstrings, **params): 

37 """ 

38 A decorator that takes docstring templates, concatenates them, and finally 

39 performs string substitution on them. 

40 This decorator will add a variable "_docstring_components" to the wrapped 

41 callable to keep track of the original docstring template for potential future use. 

42 If the docstring is a template, it will be saved as a string. 

43 Otherwise, it will be saved as a callable and the docstring will be obtained via 

44 the __doc__ attribute. 

45 This decorator cannot be used on Cython classes due to a CPython constraint, 

46 which enforces the __doc__ attribute to be read-only. 

47 See https://github.com/python/cpython/issues/91309 

48 

49 Parameters 

50 ---------- 

51 *docstrings : None, str, or callable 

52 The string / docstring / docstring template to be prepended in order 

53 before the default docstring under the callable. 

54 **params 

55 The key/value pairs used to format the docstring template. 

56 """ 

57 

58 def decorator(decorated): 

59 docstring_components = [] 

60 

61 # collect docstrings and docstring templates 

62 for docstring in docstrings: 

63 if docstring is None: 

64 continue 

65 if hasattr(docstring, "_docstring_components"): 

66 docstring_components.extend( 

67 docstring._docstring_components 

68 ) 

69 elif isinstance(docstring, str) or docstring.__doc__: 

70 docstring_components.append(docstring) 

71 

72 # append the callable's docstring last 

73 if decorated.__doc__: 

74 docstring_components.append(textwrap.dedent(decorated.__doc__)) 

75 

76 params_applied = [ 

77 component.format(**params) 

78 if isinstance(component, str) and len(params) > 0 

79 else component 

80 for component in docstring_components 

81 ] 

82 

83 decorated.__doc__ = "".join( 

84 [ 

85 component 

86 if isinstance(component, str) 

87 else textwrap.dedent(component.__doc__ or "") 

88 for component in params_applied 

89 ] 

90 ) 

91 

92 decorated._docstring_components = ( 

93 docstring_components 

94 ) 

95 return decorated 

96 

97 return decorator 

98 

99 

100def _deprecate_api(old_name, new_name, api, next_version, type=FutureWarning): 

101 msg = _DEPR_MSG.format(old_name, next_version, new_name) 

102 

103 def wrapper(*args, **kwargs): 

104 warnings.warn(msg, type) 

105 return api(*args, **kwargs) 

106 return wrapper 

107 

108 

109def _deprecate_class(old_name, new_class, next_version, 

110 instancecheck=True): 

111 """ 

112 Raise warning if a deprecated class is used in an isinstance check. 

113 """ 

114 class _DeprecatedMeta(type): 

115 def __instancecheck__(self, other): 

116 warnings.warn( 

117 _DEPR_MSG.format(old_name, next_version, new_class.__name__), 

118 FutureWarning, 

119 stacklevel=2 

120 ) 

121 return isinstance(other, new_class) 

122 

123 return _DeprecatedMeta(old_name, (new_class,), {}) 

124 

125 

126def _is_iterable(obj): 

127 try: 

128 iter(obj) 

129 return True 

130 except TypeError: 

131 return False 

132 

133 

134def _is_path_like(path): 

135 return isinstance(path, str) or hasattr(path, '__fspath__') 

136 

137 

138def _stringify_path(path): 

139 """ 

140 Convert *path* to a string or unicode path if possible. 

141 """ 

142 if isinstance(path, str): 

143 return os.path.expanduser(path) 

144 

145 # checking whether path implements the filesystem protocol 

146 try: 

147 return os.path.expanduser(path.__fspath__()) 

148 except AttributeError: 

149 pass 

150 

151 raise TypeError("not a path-like object") 

152 

153 

154def product(seq): 

155 """ 

156 Return a product of sequence items. 

157 """ 

158 return functools.reduce(lambda a, b: a*b, seq, 1) 

159 

160 

161def get_contiguous_span(shape, strides, itemsize): 

162 """ 

163 Return a contiguous span of N-D array data. 

164 

165 Parameters 

166 ---------- 

167 shape : tuple 

168 strides : tuple 

169 itemsize : int 

170 Specify array shape data 

171 

172 Returns 

173 ------- 

174 start, end : int 

175 The span end points. 

176 """ 

177 if not strides: 

178 start = 0 

179 end = itemsize * product(shape) 

180 else: 

181 start = 0 

182 end = itemsize 

183 for i, dim in enumerate(shape): 

184 if dim == 0: 

185 start = end = 0 

186 break 

187 stride = strides[i] 

188 if stride > 0: 

189 end += stride * (dim - 1) 

190 elif stride < 0: 

191 start += stride * (dim - 1) 

192 if end - start != itemsize * product(shape): 

193 raise ValueError('array data is non-contiguous') 

194 return start, end 

195 

196 

197def find_free_port(): 

198 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

199 with contextlib.closing(sock) as sock: 

200 sock.bind(('', 0)) 

201 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

202 return sock.getsockname()[1] 

203 

204 

205def guid(): 

206 from uuid import uuid4 

207 return uuid4().hex 

208 

209 

210def _break_traceback_cycle_from_frame(frame): 

211 # Clear local variables in all inner frames, so as to break the 

212 # reference cycle. 

213 this_frame = sys._getframe(0) 

214 refs = gc.get_referrers(frame) 

215 while refs: 

216 for frame in refs: 

217 if frame is not this_frame and isinstance(frame, types.FrameType): 

218 break 

219 else: 

220 # No frame found in referrers (finished?) 

221 break 

222 refs = None 

223 # Clear the frame locals, to try and break the cycle (it is 

224 # somewhere along the chain of execution frames). 

225 frame.clear() 

226 # To visit the inner frame, we need to find it among the 

227 # referrers of this frame (while `frame.f_back` would let 

228 # us visit the outer frame). 

229 refs = gc.get_referrers(frame) 

230 refs = frame = this_frame = None 

231 

232 

233def _download_urllib(url, out_path): 

234 from urllib.request import urlopen 

235 with urlopen(url) as response: 

236 with open(out_path, 'wb') as f: 

237 f.write(response.read()) 

238 

239 

240def _download_requests(url, out_path): 

241 import requests 

242 with requests.get(url) as response: 

243 with open(out_path, 'wb') as f: 

244 f.write(response.content) 

245 

246 

247def download_tzdata_on_windows(): 

248 r""" 

249 Download and extract latest IANA timezone database into the 

250 location expected by Arrow which is %USERPROFILE%\Downloads\tzdata. 

251 """ 

252 if sys.platform != 'win32': 

253 raise TypeError(f"Timezone database is already provided by {sys.platform}") 

254 

255 import tarfile 

256 

257 tzdata_url = "https://data.iana.org/time-zones/tzdata-latest.tar.gz" 

258 tzdata_path = os.path.expandvars(r"%USERPROFILE%\Downloads\tzdata") 

259 tzdata_compressed_path = os.path.join(tzdata_path, "tzdata.tar.gz") 

260 windows_zones_url = "https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml" # noqa 

261 windows_zones_path = os.path.join(tzdata_path, "windowsZones.xml") 

262 os.makedirs(tzdata_path, exist_ok=True) 

263 

264 # Try to download the files with requests and then fall back to urllib. This 

265 # works around possible issues in certain older environment (GH-45295) 

266 try: 

267 _download_requests(tzdata_url, tzdata_compressed_path) 

268 _download_requests(windows_zones_url, windows_zones_path) 

269 except ImportError: 

270 _download_urllib(tzdata_url, tzdata_compressed_path) 

271 _download_urllib(windows_zones_url, windows_zones_path) 

272 

273 assert os.path.exists(tzdata_compressed_path) 

274 assert os.path.exists(windows_zones_path) 

275 

276 tarfile.open(tzdata_compressed_path).extractall(tzdata_path)