|
16 | 16 | # because this module is imported many places (but not always used)! |
17 | 17 |
|
18 | 18 | import inspect |
| 19 | +import io |
19 | 20 | import operator as operator_module |
20 | 21 | import os |
21 | 22 | import warnings |
22 | 23 | from math import log |
23 | 24 |
|
24 | 25 | import numpy as np |
| 26 | +import numpy.typing |
25 | 27 | from packaging.version import parse |
26 | 28 |
|
27 | 29 | ############################################################################### |
@@ -733,3 +735,33 @@ def sph_harm_y(n, m, theta, phi, *, diff_n=0): |
733 | 735 | return special.sph_harm_y(n, m, theta, phi, diff_n=diff_n) |
734 | 736 | else: |
735 | 737 | return special.sph_harm(m, n, phi, theta) |
| 738 | + |
| 739 | + |
| 740 | +############################################################################### |
| 741 | +# workaround: Numpy won't allow to read from file-like objects with numpy.fromfile, |
| 742 | +# we try to use numpy.fromfile, if a blob is used we use numpy.frombuffer to read |
| 743 | +# from the file-like object. |
| 744 | +def read_from_file_or_buffer( |
| 745 | + file: str | bytes | os.PathLike | io.IOBase, |
| 746 | + dtype: numpy.typing.DTypeLike = float, |
| 747 | + count: int = -1, |
| 748 | +): |
| 749 | + """numpy.fromfile() wrapper, handling io.BytesIO file-like streams. |
| 750 | +
|
| 751 | + Numpy requires open files to be actual files on disk, i.e., must support |
| 752 | + file.fileno(), so it fails with file-like streams such as io.BytesIO(). |
| 753 | +
|
| 754 | + If numpy.fromfile() fails due to no file.fileno() support, this wrapper |
| 755 | + reads the required bytes from file and redirects the call to |
| 756 | + numpy.frombuffer(). |
| 757 | +
|
| 758 | + See https://github.com/numpy/numpy/issues/2230#issuecomment-949795210 |
| 759 | + """ |
| 760 | + try: |
| 761 | + return np.fromfile(file, dtype=dtype, count=count) |
| 762 | + except io.UnsupportedOperation as e: |
| 763 | + if not (e.args and e.args[0] == "fileno" and isinstance(file, io.IOBase)): |
| 764 | + raise # Nothing I can do about it |
| 765 | + dtype = np.dtype(dtype) |
| 766 | + buffer = file.read(dtype.itemsize * count) |
| 767 | + return np.frombuffer(buffer, dtype=dtype, count=count) |
0 commit comments