ronantakizawa/codereview-bench huggingface dataset:
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:

    Dimensions as individual arguments

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)
    
    Notes
    -----
    New in version X.Y.Z.
    As of NumPy 2.3.0.dev0, this iterator is implemented using `itertools.product`
    from Python's standard library. This change provides significant improvements
    in both performance and and memory efficiency, particularly for large iteration
    spaces, while maintaining the original behavior and interface.

    """


    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        self.shape = shape
        self._iter = product(*(range(s) for s in shape))


    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0

Review comment (suggestion):
This text seems fine for a release note. But since the interface is unchanged, I would leave it out if the user documentation.

Code after:

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:
    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)
    
    Notes
    -----
    As of NumPy 2.4.0.dev0, this iterator is implemented using `itertools.product`
    from Python's standard library. This change provides significant improvements
    in both performance and memory efficiency, particularly for large iteration
    spaces, while maintaining the original behavior and interface.

    """


    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        self.shape = shape
        self._iter = product(*(range(s) for s in shape))
        


    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
        Standard iterator method, updates the index and returns the index

Review comment (suggestion):
feel free to ignore this, but a `map` would also work here:

```suggestion
        self._iter = product(*map(range, shape))
```

Code after:
    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
        Standard iterator method, updates the index and returns the index
        tuple.

        Returns
        -------
        val : tuple of ints
            Returns a tuple containing the indices of the current
            iteration.

        """
        return next(self._iter)
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:
    --------
    >>> import numpy as np

    Dimensions as individual arguments

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

     Notes
    -----
    As of NumPy 2.4.0.dev0, this iterator is implemented using `itertools.product`
    from Python's standard library. This change provides significant improvements
    in both performance and memory efficiency, particularly for large iteration
    spaces, while maintaining the original behavior and interface.
     """
    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        self.shape = shape
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """

Review comment (suggestion):
This should be in a release note rather than here. See the comments in `doc/release/upcoming_changes/README.rst`

Code after:
    --------
    >>> import numpy as np

    Dimensions as individual arguments

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

     """
    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if any(dim < 0 for dim in shape):
            raise ValueError("negative dimensions are not allowed")
        self.shape = shape
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """

Review comment (suggestion):
```suggestion
        if min(shape) < 0:
```
Is perhaps faster, as it avoids creation of a generator.

Code after:

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
Repository: numpy/numpy
File: numpy/lib/tests/test_index_tricks.py (Python)

Code before:
def test_ndindex_large_dimensions_behavior():
    """Test ndindex behaves correctly when initialized with large dimensions."""
    large_shape = (1000, 1000)
    iter_obj = np.ndindex(*large_shape)
    first_element = next(iter_obj)
    assert_equal(first_element, (0, 0))

def test_ndindex_empty_iterator_behavior():
    """Test detailed behavior of empty iterators."""
    empty_iter = np.ndindex(0, 5)
    assert_equal(list(empty_iter), [])

    empty_iter2 = np.ndindex(3, 0, 2)
    with pytest.raises(StopIteration):
        next(empty_iter2)

@pytest.mark.parametrize("negative_shape_arg", [
    (-1,),          # Single negative dimension
    (2, -3, 4),     # Negative dimension in the middle
    (5, 0, -2)      # Mix of valid (0) and invalid (negative) dimensions
])
def test_ndindex_negative_dimensions(negative_shape_arg):
    """Test that negative dimensions raise ValueError."""
    with pytest.raises(ValueError):
        # ndindex should raise ValueError immediately for negative dimensions
        list(ndindex(negative_shape_arg))


Review comment (suggestion):
```suggestion
        ndindex(negative_shape_arg)
```

Code after:
        (1, 0, 1),
        (1, 0, 2),
    ]
    assert_equal(result, expected)


def test_ndindex_large_dimensions_behavior():
    """Test ndindex behaves correctly when initialized with large dimensions."""
    large_shape = (1000, 1000)
    iter_obj = np.ndindex(*large_shape)
    first_element = next(iter_obj)
    assert_equal(first_element, (0, 0))


def test_ndindex_empty_iterator_behavior():
    """Test detailed behavior of empty iterators."""
    empty_iter = np.ndindex(0, 5)
    assert_equal(list(empty_iter), [])

    empty_iter2 = np.ndindex(3, 0, 2)
    with pytest.raises(StopIteration):
        next(empty_iter2)


@pytest.mark.parametrize(
    "negative_shape_arg",
    [
        (-1,),  # Single negative dimension
        (2, -3, 4),  # Negative dimension in the middle
        (5, 0, -2),  # Mix of valid (0) and invalid (negative) dimensions
    ],
)
def test_ndindex_negative_dimensions(negative_shape_arg):
    """Test that negative dimensions raise ValueError."""
    with pytest.raises(ValueError):
        ndindex(negative_shape_arg)


def test_ndindex_empty_shape():
    import numpy as np
    # ndindex() and ndindex(()) should return a single empty tuple
    assert list(np.ndindex()) == [()]
    assert list(np.ndindex(())) == [()]

def test_ndindex_negative_dim_raises():
    # ndindex(-1) should raise a ValueError
    with pytest.raises(ValueError):
        list(np.ndindex(-1))
Repository: numpy/numpy
File: numpy/lib/__init__.py (Python)

Code before:
    _shape_base_impl,
    _stride_tricks_impl,
    _twodim_base_impl,
    _type_check_impl,
    _ufunclike_impl,
    _utils_impl,
    _version,
    array_utils,
    format,
    introspect,
    mixins,
    npyio,
    scimath,
    stride_tricks,
)

# numpy.lib namespace members
from ._arrayterator_impl import Arrayterator
from ._version import NumpyVersion
from ._index_tricks_impl import ndindex
ndindex.__module__ = "numpy.lib"

__all__ = [
    "Arrayterator", "add_docstring", "add_newdoc", "array_utils",
    "format", "introspect", "mixins", "NumpyVersion", "npyio", "scimath",
    "stride_tricks", "tracemalloc_domain", "ndindex",
]

add_newdoc.__module__ = "numpy.lib"

from numpy._pytesttester import PytestTester

test = PytestTester(__name__)
del PytestTester

def __getattr__(attr):
    # Warn for deprecated/removed aliases
    import math
    import warnings

    if attr == "math":
        warnings.warn(
            "`np.lib.math` is a deprecated alias for the standard library "
            "`math` module (Deprecated Numpy 1.25). Replace usages of "
            "`numpy.lib.math` with `math`", DeprecationWarning, stacklevel=2)
        return math
    elif attr == "emath":
        raise AttributeError(
            "numpy.lib.emath was an alias for emath module that was removed "
            "in NumPy 2.0. Replace usages of numpy.lib.emath with "
            "numpy.emath.",

Review comment (bug):
The addition of `ndindex` is making the CI fail. Either remove it here, or add it to https://github.com/numpy/numpy/blob/main/numpy/tests/test_public_api.py.

(Since `ndindex` was not present before in the namespace, my first reaction would be to keep it out)

Code after:
    _shape_base_impl,
    _stride_tricks_impl,
    _twodim_base_impl,
    _type_check_impl,
    _ufunclike_impl,
    _utils_impl,
    _version,
    array_utils,
    format,
    introspect,
    mixins,
    npyio,
    scimath,
    stride_tricks,
)

# numpy.lib namespace members
from ._arrayterator_impl import Arrayterator
from ._version import NumpyVersion

__all__ = [
    "Arrayterator", "add_docstring", "add_newdoc", "array_utils",
    "format", "introspect", "mixins", "NumpyVersion", "npyio", "scimath",
    "stride_tricks", "tracemalloc_domain",
]

add_newdoc.__module__ = "numpy.lib"

from numpy._pytesttester import PytestTester

test = PytestTester(__name__)
del PytestTester

def __getattr__(attr):
    # Warn for deprecated/removed aliases
    import math
    import warnings

    if attr == "math":
        warnings.warn(
            "`np.lib.math` is a deprecated alias for the standard library "
            "`math` module (Deprecated Numpy 1.25). Replace usages of "
            "`numpy.lib.math` with `math`", DeprecationWarning, stacklevel=2)
        return math
    elif attr == "emath":
        raise AttributeError(
            "numpy.lib.emath was an alias for emath module that was removed "
            "in NumPy 2.0. Replace usages of numpy.lib.emath with "
            "numpy.emath.",
            name=None
        )
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

     """
    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape) < 0:
            raise ValueError("negative dimensions are not allowed")
        self.shape = shape
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """

Review comment (suggestion):
```suggestion
        if min(shape, default=0) < 0:
```
(to handle the case where shape is empty)

Code after:

    >>> for index in np.ndindex(3, 2, 1):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
Repository: numpy/numpy
File: numpy/lib/_index_tricks_impl.py (Python)

Code before:
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self.shape = shape
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
        Standard iterator method, updates the index and returns the index
        tuple.

Review comment (suggestion):
This introduces a new public `nditer.shape` attribute. But because it's not used for anything, and because public attributes require documentation (and a motivation), I think we should remove it.

```suggestion
```

Code after:
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    Same dimensions - but in a tuple ``(3, 2, 1)``

    >>> for index in np.ndindex((3, 2, 1)):
    ...     print(index)
    (0, 0, 0)
    (0, 1, 0)
    (1, 0, 0)
    (1, 1, 0)
    (2, 0, 0)
    (2, 1, 0)

    """

    def __init__(self, *shape):
        if len(shape) == 1 and isinstance(shape[0], tuple):
            shape = shape[0]
        if min(shape, default=0) < 0:
            raise ValueError("negative dimensions are not allowed")
        self._iter = product(*map(range, shape))

    def __iter__(self):
        return self

    def ndincr(self):
        """
        Increment the multi-dimensional index by one.

        This method is for backward compatibility only: do not use.

        .. deprecated:: 1.20.0
            This method has been advised against since numpy 1.8.0, but only
            started emitting DeprecationWarning as of this version.
        """
        # NumPy 1.20.0, 2020-09-08
        warnings.warn(
            "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead",
            DeprecationWarning, stacklevel=2)
        next(self)

    def __next__(self):
        """
        Standard iterator method, updates the index and returns the index
        tuple.