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
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
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.
18# Miscellaneous utility code
20import os
21import contextlib
22import functools
23import gc
24import socket
25import sys
26import textwrap
27import types
28import warnings
31_DEPR_MSG = (
32 "pyarrow.{} is deprecated as of {}, please use pyarrow.{} instead."
33)
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
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 """
58 def decorator(decorated):
59 docstring_components = []
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)
72 # append the callable's docstring last
73 if decorated.__doc__:
74 docstring_components.append(textwrap.dedent(decorated.__doc__))
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 ]
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 )
92 decorated._docstring_components = (
93 docstring_components
94 )
95 return decorated
97 return decorator
100def _deprecate_api(old_name, new_name, api, next_version, type=FutureWarning):
101 msg = _DEPR_MSG.format(old_name, next_version, new_name)
103 def wrapper(*args, **kwargs):
104 warnings.warn(msg, type)
105 return api(*args, **kwargs)
106 return wrapper
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)
123 return _DeprecatedMeta(old_name, (new_class,), {})
126def _is_iterable(obj):
127 try:
128 iter(obj)
129 return True
130 except TypeError:
131 return False
134def _is_path_like(path):
135 return isinstance(path, str) or hasattr(path, '__fspath__')
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)
145 # checking whether path implements the filesystem protocol
146 try:
147 return os.path.expanduser(path.__fspath__())
148 except AttributeError:
149 pass
151 raise TypeError("not a path-like object")
154def product(seq):
155 """
156 Return a product of sequence items.
157 """
158 return functools.reduce(lambda a, b: a*b, seq, 1)
161def get_contiguous_span(shape, strides, itemsize):
162 """
163 Return a contiguous span of N-D array data.
165 Parameters
166 ----------
167 shape : tuple
168 strides : tuple
169 itemsize : int
170 Specify array shape data
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
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]
205def guid():
206 from uuid import uuid4
207 return uuid4().hex
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
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())
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)
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}")
255 import tarfile
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)
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)
273 assert os.path.exists(tzdata_compressed_path)
274 assert os.path.exists(windows_zones_path)
276 tarfile.open(tzdata_compressed_path).extractall(tzdata_path)