Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4f84d71

Browse files
authored
Merge pull request #24540 from mtsokol/lib-arrayutils-namespace
API: Add ``lib.array_utils`` namespace
2 parents cba1869 + 383abbc commit 4f84d71

21 files changed

+153
-110
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* ``np.lib.array_utils`` public module has been introduced and in its initial version
2+
it hosts three functions: ``byte_bounds`` (moved from ``np.lib.utils``),
3+
``normalize_axis_tuple`` and ``normalize_axis_index``

doc/source/reference/routines.other.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Memory ranges
2121

2222
shares_memory
2323
may_share_memory
24-
byte_bounds
24+
lib.array_utils.byte_bounds
2525

2626
Array mixins
2727
------------
@@ -47,6 +47,8 @@ Utility
4747
show_config
4848
show_runtime
4949
broadcast_shapes
50+
lib.array_utils.normalize_axis_index
51+
lib.array_utils.normalize_axis_tuple
5052

5153
.. automodule:: numpy.exceptions
5254

numpy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@
218218
from .lib._ufunclike_impl import fix, isneginf, isposinf
219219
from .lib._arraypad_impl import pad
220220
from .lib._utils_impl import (
221-
byte_bounds, show_runtime, get_include, info
221+
show_runtime, get_include, info
222222
)
223223
from .lib._stride_tricks_impl import (
224224
broadcast_arrays, broadcast_shapes, broadcast_to

numpy/__init__.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,6 @@ from numpy.lib._ufunclike_impl import (
577577
from numpy.lib._utils_impl import (
578578
get_include as get_include,
579579
info as info,
580-
byte_bounds as byte_bounds,
581580
show_runtime as show_runtime,
582581
)
583582

numpy/_expired_attrs_2_0.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
"`scalar_types` argument, use `numpy.result_type` and pass the "
6666
"Python values `0`, `0.0`, or `0j`.",
6767
"round_": "Use `np.round` instead.",
68-
"nbytes": "Use `np.dtype(<dtype>).itemsize` instead.",
6968
"get_array_wrap": "",
7069
"DataSource": "It's still available as `np.lib.npyio.DataSource`.",
70+
"nbytes": "Use `np.dtype(<dtype>).itemsize` instead.",
71+
"byte_bounds": "Now it's available under `np.lib.array_utils.byte_bounds`",
7172
}

numpy/core/multiarray.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
zeros.__module__ = 'numpy'
7070
_get_promotion_state.__module__ = 'numpy'
7171
_set_promotion_state.__module__ = 'numpy'
72+
normalize_axis_index.__module__ = 'numpy.lib.array_utils'
7273

7374

7475
# We can't verify dispatcher signatures because NumPy's C functions don't

numpy/core/numeric.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ def rollaxis(a, axis, start=0):
13281328
return a.transpose(axes)
13291329

13301330

1331+
@set_module("numpy.lib.array_utils")
13311332
def normalize_axis_tuple(axis, ndim, argname=None, allow_duplicate=False):
13321333
"""
13331334
Normalizes an axis argument into a tuple of non-negative integer axes.

numpy/lib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from . import npyio
3737
from . import arrayterator
3838
from . import _arraypad_impl
39+
from . import array_utils
3940
from . import _version
4041

4142
from .arrayterator import Arrayterator

numpy/lib/_array_utils_impl.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from numpy.core import asarray
2+
from numpy.core.numeric import normalize_axis_tuple, normalize_axis_index
3+
from numpy._utils import set_module
4+
5+
__all__ = ["byte_bounds", "normalize_axis_tuple", "normalize_axis_index"]
6+
7+
8+
@set_module("numpy.lib.array_utils")
9+
def byte_bounds(a):
10+
"""
11+
Returns pointers to the end-points of an array.
12+
13+
Parameters
14+
----------
15+
a : ndarray
16+
Input array. It must conform to the Python-side of the array
17+
interface.
18+
19+
Returns
20+
-------
21+
(low, high) : tuple of 2 integers
22+
The first integer is the first byte of the array, the second
23+
integer is just past the last byte of the array. If `a` is not
24+
contiguous it will not use every byte between the (`low`, `high`)
25+
values.
26+
27+
Examples
28+
--------
29+
>>> I = np.eye(2, dtype='f'); I.dtype
30+
dtype('float32')
31+
>>> low, high = np.byte_bounds(I)
32+
>>> high - low == I.size*I.itemsize
33+
True
34+
>>> I = np.eye(2); I.dtype
35+
dtype('float64')
36+
>>> low, high = np.byte_bounds(I)
37+
>>> high - low == I.size*I.itemsize
38+
True
39+
40+
"""
41+
ai = a.__array_interface__
42+
a_data = ai['data'][0]
43+
astrides = ai['strides']
44+
ashape = ai['shape']
45+
bytes_a = asarray(a).dtype.itemsize
46+
47+
a_low = a_high = a_data
48+
if astrides is None:
49+
# contiguous case
50+
a_high += a.size * bytes_a
51+
else:
52+
for shape, stride in zip(ashape, astrides):
53+
if stride < 0:
54+
a_low += (shape-1)*stride
55+
else:
56+
a_high += (shape-1)*stride
57+
a_high += bytes_a
58+
return a_low, a_high

numpy/lib/_array_utils_impl.pyi

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from typing import Any, Iterable, Tuple
2+
3+
from numpy import generic
4+
from numpy.typing import NDArray
5+
6+
__all__: list[str]
7+
8+
# NOTE: In practice `byte_bounds` can (potentially) take any object
9+
# implementing the `__array_interface__` protocol. The caveat is
10+
# that certain keys, marked as optional in the spec, must be present for
11+
# `byte_bounds`. This concerns `"strides"` and `"data"`.
12+
def byte_bounds(a: generic | NDArray[Any]) -> tuple[int, int]: ...
13+
14+
def normalize_axis_tuple(
15+
axis: int | Iterable[int],
16+
ndim: int = ...,
17+
argname: None | str = ...,
18+
allow_duplicate: None | bool = ...,
19+
) -> Tuple[int, int]: ...
20+
21+
def normalize_axis_index(
22+
axis: int = ...,
23+
ndim: int = ...,
24+
msg_prefix: None | str = ...,
25+
) -> int: ...

numpy/lib/_utils_impl.py

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
import functools
88
import platform
99

10-
from numpy.core import ndarray, asarray
10+
from numpy.core import ndarray
1111
from numpy._utils import set_module
1212
import numpy as np
1313

1414
__all__ = [
15-
'get_include', 'info', 'byte_bounds', 'show_runtime'
15+
'get_include', 'info', 'show_runtime'
1616
]
1717

1818

@@ -287,64 +287,6 @@ def deprecate_with_doc(msg):
287287
return _Deprecate(message=msg)
288288

289289

290-
#--------------------------------------------
291-
# Determine if two arrays can share memory
292-
#--------------------------------------------
293-
294-
295-
@set_module('numpy')
296-
def byte_bounds(a):
297-
"""
298-
Returns pointers to the end-points of an array.
299-
300-
Parameters
301-
----------
302-
a : ndarray
303-
Input array. It must conform to the Python-side of the array
304-
interface.
305-
306-
Returns
307-
-------
308-
(low, high) : tuple of 2 integers
309-
The first integer is the first byte of the array, the second
310-
integer is just past the last byte of the array. If `a` is not
311-
contiguous it will not use every byte between the (`low`, `high`)
312-
values.
313-
314-
Examples
315-
--------
316-
>>> I = np.eye(2, dtype='f'); I.dtype
317-
dtype('float32')
318-
>>> low, high = np.byte_bounds(I)
319-
>>> high - low == I.size*I.itemsize
320-
True
321-
>>> I = np.eye(2); I.dtype
322-
dtype('float64')
323-
>>> low, high = np.byte_bounds(I)
324-
>>> high - low == I.size*I.itemsize
325-
True
326-
327-
"""
328-
ai = a.__array_interface__
329-
a_data = ai['data'][0]
330-
astrides = ai['strides']
331-
ashape = ai['shape']
332-
bytes_a = asarray(a).dtype.itemsize
333-
334-
a_low = a_high = a_data
335-
if astrides is None:
336-
# contiguous case
337-
a_high += a.size * bytes_a
338-
else:
339-
for shape, stride in zip(ashape, astrides):
340-
if stride < 0:
341-
a_low += (shape-1)*stride
342-
else:
343-
a_high += (shape-1)*stride
344-
a_high += bytes_a
345-
return a_low, a_high
346-
347-
348290
#-----------------------------------------------------------------------------
349291

350292

numpy/lib/_utils_impl.pyi

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ from typing import (
77
Protocol,
88
)
99

10-
from numpy import generic
11-
from numpy.typing import NDArray
1210
from numpy.core.numerictypes import (
1311
issubdtype as issubdtype,
1412
)
@@ -56,12 +54,6 @@ def deprecate(
5654

5755
def deprecate_with_doc(msg: None | str) -> _Deprecate: ...
5856

59-
# NOTE: In practice `byte_bounds` can (potentially) take any object
60-
# implementing the `__array_interface__` protocol. The caveat is
61-
# that certain keys, marked as optional in the spec, must be present for
62-
# `byte_bounds`. This concerns `"strides"` and `"data"`.
63-
def byte_bounds(a: generic | NDArray[Any]) -> tuple[int, int]: ...
64-
6557
def info(
6658
object: object = ...,
6759
maxwidth: int = ...,

numpy/lib/array_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from ._array_utils_impl import (
2+
__all__,
3+
byte_bounds,
4+
normalize_axis_index,
5+
normalize_axis_tuple,
6+
)

numpy/lib/array_utils.pyi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from ._array_utils_impl import (
2+
__all__ as __all__,
3+
byte_bounds as byte_bounds,
4+
normalize_axis_index as normalize_axis_index,
5+
normalize_axis_tuple as normalize_axis_tuple,
6+
)

numpy/lib/tests/test_array_utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import numpy as np
2+
3+
from numpy.lib import array_utils
4+
from numpy.testing import assert_equal
5+
6+
7+
class TestByteBounds:
8+
def test_byte_bounds(self):
9+
# pointer difference matches size * itemsize
10+
# due to contiguity
11+
a = np.arange(12).reshape(3, 4)
12+
low, high = array_utils.byte_bounds(a)
13+
assert_equal(high - low, a.size * a.itemsize)
14+
15+
def test_unusual_order_positive_stride(self):
16+
a = np.arange(12).reshape(3, 4)
17+
b = a.T
18+
low, high = array_utils.byte_bounds(b)
19+
assert_equal(high - low, b.size * b.itemsize)
20+
21+
def test_unusual_order_negative_stride(self):
22+
a = np.arange(12).reshape(3, 4)
23+
b = a.T[::-1]
24+
low, high = array_utils.byte_bounds(b)
25+
assert_equal(high - low, b.size * b.itemsize)
26+
27+
def test_strided(self):
28+
a = np.arange(12)
29+
b = a[::2]
30+
low, high = array_utils.byte_bounds(b)
31+
# the largest pointer address is lost (even numbers only in the
32+
# stride), and compensate addresses for striding by 2
33+
assert_equal(high - low, b.size * 2 * b.itemsize - b.itemsize)

numpy/lib/tests/test_utils.py

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,12 @@
11
import pytest
22

33
import numpy as np
4-
from numpy.testing import assert_equal, assert_raises_regex
4+
from numpy.testing import assert_raises_regex
55
import numpy.lib._utils_impl as _utils_impl
66

77
from io import StringIO
88

99

10-
class TestByteBounds:
11-
12-
def test_byte_bounds(self):
13-
# pointer difference matches size * itemsize
14-
# due to contiguity
15-
a = np.arange(12).reshape(3, 4)
16-
low, high = np.byte_bounds(a)
17-
assert_equal(high - low, a.size * a.itemsize)
18-
19-
def test_unusual_order_positive_stride(self):
20-
a = np.arange(12).reshape(3, 4)
21-
b = a.T
22-
low, high = np.byte_bounds(b)
23-
assert_equal(high - low, b.size * b.itemsize)
24-
25-
def test_unusual_order_negative_stride(self):
26-
a = np.arange(12).reshape(3, 4)
27-
b = a.T[::-1]
28-
low, high = np.byte_bounds(b)
29-
assert_equal(high - low, b.size * b.itemsize)
30-
31-
def test_strided(self):
32-
a = np.arange(12)
33-
b = a[::2]
34-
low, high = np.byte_bounds(b)
35-
# the largest pointer address is lost (even numbers only in the
36-
# stride), and compensate addresses for striding by 2
37-
assert_equal(high - low, b.size * 2 * b.itemsize - b.itemsize)
38-
39-
4010
def test_assert_raises_regex_context_manager():
4111
with assert_raises_regex(ValueError, 'no deprecation warning'):
4212
raise ValueError('no deprecation warning')

numpy/tests/test_public_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def test_NPY_NO_EXPORT():
123123
"lib.stride_tricks",
124124
"lib.npyio",
125125
"lib.introspect",
126+
"lib.array_utils",
126127
"linalg",
127128
"ma",
128129
"ma.extras",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import numpy as np
1+
import numpy.lib.array_utils as array_utils
22

3-
np.byte_bounds(1) # E: incompatible type
3+
array_utils.byte_bounds(1) # E: incompatible type

numpy/typing/tests/data/pass/lib_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from io import StringIO
44

55
import numpy as np
6+
import numpy.lib.array_utils as array_utils
67

78
FILE = StringIO()
89
AR = np.arange(10, dtype=np.float64)
@@ -12,8 +13,7 @@ def func(a: int) -> bool:
1213
return True
1314

1415

15-
np.byte_bounds(AR)
16-
np.byte_bounds(np.float64())
16+
array_utils.byte_bounds(AR)
17+
array_utils.byte_bounds(np.float64())
1718

1819
np.info(1, output=FILE)
19-

numpy/typing/tests/data/pass/modules.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
np.lib.mixins
2020
np.lib.scimath
2121
np.lib.stride_tricks
22+
np.lib.array_utils
2223
np.ma.extras
2324
np.polynomial.chebyshev
2425
np.polynomial.hermite

0 commit comments

Comments
 (0)