You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classat: # pylint: disable=invalid-name # numpydoc ignore=PR02""" Update operations for read-only arrays. This implements ``jax.numpy.ndarray.at`` for all writeable backends (those that support ``__setitem__``) and routes to the ``.at[]`` method for JAX arrays. Parameters ---------- x : array Input array. idx : index, optional Only `array API standard compliant indices <https://data-apis.org/array-api/latest/API_specification/indexing.html>`_ are supported. You may use two alternate syntaxes:: at(x, idx).set(value) # or add(value), etc. at(x)[idx].set(value) copy : bool, optional True (default) Ensure that the inputs are not modified. False Ensure that the update operation writes back to the input. Raise ``ValueError`` if a copy cannot be avoided. None The array parameter *may* be modified in place if it is possible and beneficial for performance. You should not reuse it after calling this function. xp : array_namespace, optional The standard-compatible namespace for `x`. Default: infer. Returns ------- Updated input array. Warnings -------- (a) When you use ``copy=None``, you should always immediately overwrite the parameter array:: x = at(x, 0).set(2, copy=None) The anti-pattern below must be avoided, as it will result in different behaviour on read-only versus writeable arrays:: x = xp.asarray([0, 0, 0]) y = at(x, 0).set(2, copy=None) z = at(x, 1).set(3, copy=None) In the above example, ``x == [0, 0, 0]``, ``y == [2, 0, 0]`` and z == ``[0, 3, 0]`` when ``x`` is read-only, whereas ``x == y == z == [2, 3, 0]`` when ``x`` is writeable! (b) The array API standard does not support integer array indices. The behaviour of update methods when the index is an array of integers is undefined and will vary between backends; this is particularly true when the index contains multiple occurrences of the same index, e.g.:: >>> import numpy as np >>> import jax.numpy as jnp >>> at(np.asarray([123]), np.asarray([0, 0])).add(1) array([124]) >>> at(jnp.asarray([123]), jnp.asarray([0, 0])).add(1) Array([125], dtype=int32) See Also -------- jax.numpy.ndarray.at : Equivalent array method in JAX. Notes ----- `sparse <https://sparse.pydata.org/>`_, as well as read-only arrays from libraries not explicitly covered by ``array-api-compat``, are not supported by update methods. Examples -------- Given either of these equivalent expressions:: x = at(x)[1].add(2, copy=None) x = at(x, 1).add(2, copy=None) If x is a JAX array, they are the same as:: x = x.at[1].add(2) If x is a read-only numpy array, they are the same as:: x = x.copy() x[1] += 2 For other known backends, they are the same as:: x[1] += 2 """_x: Array_idx: Index__slots__: ClassVar[tuple[str, ...]] = ("_idx", "_x")
def__init__(
self, x: Array, idx: Index=_undef, /
) ->None: # numpydoc ignore=GL08self._x=xself._idx=idxdef__getitem__(self, idx: Index, /) ->"at": # numpydoc ignore=PR01,RT01""" Allow for the alternate syntax ``at(x)[start:stop:step]``. It looks prettier than ``at(x, slice(start, stop, step))`` and feels more intuitive coming from the JAX documentation. """ifself._idxisnot_undef:
msg="Index has already been set"raiseValueError(msg)
self._idx=idxreturnselfdef_update_common(
self,
at_op: str,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->tuple[Array, None] |tuple[None, Array]: # numpydoc ignore=PR01""" Perform common prepocessing to all update operations. Returns ------- tuple If the operation can be resolved by ``at[]``, ``(return value, None)`` Otherwise, ``(None, preprocessed x)``. """x, idx=self._x, self._idxifidxis_undef:
msg= (
"Index has not been set.\n""Usage: either\n"" at(x, idx).set(value)\n""or\n"" at(x)[idx].set(value)\n""(same for all other methods)."
)
raiseValueError(msg)
ifcopynotin (True, False, None):
msg=f"copy must be True, False, or None; got {copy!r}"# pyright: ignore[reportUnreachable]raiseValueError(msg)
ifcopyisNone:
writeable=is_writeable_array(x)
copy=notwriteableelifcopy:
writeable=Noneelse:
writeable=is_writeable_array(x)
ifcopy:
ifis_jax_array(x):
# Use JAX's at[]func=getattr(x.at[idx], at_op)
returnfunc(y), None# Emulate at[] behaviour for non-JAX arrays# with a copy followed by an updateifxpisNone:
xp=array_namespace(x)
x=xp.asarray(x, copy=True)
ifwriteableisFalse:
# A copy of a read-only numpy array is writeable# Note: this assumes that a copy of a writeable array is writeablewriteable=NoneifwriteableisNone:
writeable=is_writeable_array(x)
ifnotwriteable:
# sparse crashes heremsg=f"Can't update read-only array {x}"raiseValueError(msg)
returnNone, xdefset(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] = y`` and return the update array."""res, x=self._update_common("set", y, copy=copy, xp=xp)
ifresisnotNone:
returnresassertxisnotNonex[self._idx] =yreturnxdef_iop(
self,
at_op: Literal[
"set", "add", "subtract", "multiply", "divide", "power", "min", "max"
],
elwise_op: Callable[[Array, Array], Array],
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01""" ``x[idx] += y`` or equivalent in-place operation on a subset of x. which is the same as saying x[idx] = x[idx] + y Note that this is not the same as operator.iadd(x[idx], y) Consider for example when x is a numpy array and idx is a fancy index, which triggers a deep copy on __getitem__. """res, x=self._update_common(at_op, y, copy=copy, xp=xp)
ifresisnotNone:
returnresassertxisnotNonex[self._idx] =elwise_op(x[self._idx], y)
returnxdefadd(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] += y`` and return the updated array."""returnself._iop("add", operator.add, y, copy=copy, xp=xp)
defsubtract(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] -= y`` and return the updated array."""returnself._iop("subtract", operator.sub, y, copy=copy, xp=xp)
defmultiply(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] *= y`` and return the updated array."""returnself._iop("multiply", operator.mul, y, copy=copy, xp=xp)
defdivide(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] /= y`` and return the updated array."""returnself._iop("divide", operator.truediv, y, copy=copy, xp=xp)
defpower(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] **= y`` and return the updated array."""returnself._iop("power", operator.pow, y, copy=copy, xp=xp)
defmin(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] = minimum(x[idx], y)`` and return the updated array."""ifxpisNone:
xp=array_namespace(self._x)
y=xp.asarray(y)
returnself._iop("min", xp.minimum, y, copy=copy, xp=xp)
defmax(
self,
y: Array,
/,
copy: bool|None=True,
xp: ModuleType|None=None,
) ->Array: # numpydoc ignore=PR01,RT01"""Apply ``x[idx] = maximum(x[idx], y)`` and return the updated array."""ifxpisNone:
xp=array_namespace(self._x)
y=xp.asarray(y)
returnself._iop("max", xp.maximum, y, copy=copy, xp=xp)
Please trim the code to make it a Minimal Reproducible Example. The example you posted seems more like a code dump than something minimal.
You don't explain what's the point you're trying to make.... Numpydoc isn't Sphinx, it's an extension to Sphinx so why shouldn't the extension be handling those changes?
You don't include a screenshot of the proposed changes for ease of reading.
Isn't rendered order controlled by declaration order (also considering the complex case of mixing docstring with reST declarations)? In that scenario how to you propose mixed declaration order be solved (again the form of your proposal is very shallow for not being self-explanatory of the more complex use cases).
thanks for taking a look, I can try to address points (1) and (3) when I find the time.
You don't explain what's the point you're trying to make.... Numpydoc isn't Sphinx, it's an extension to Sphinx so why shouldn't the extension be handling those changes?
To quote the Napoleon docs:
Napoleon is a extension that enables Sphinx to parse both NumPy and Google style docstrings
My understanding is that Napoleon should format the docstrings as Numpydoc would. Unless it has its own separate style? If so, it would be good to make that clear in the docs.
I agree that Sphinx should update the style to reflect what is defined by NumPy. This is what Napoleon links to internally, so I think this is the best course of action.
Describe the bug
As noted in the release notes for numpydoc 1.8.0, the section ordering was updated in numpy/numpydoc#571 for classes, to move the Attributes and Methods sections directly below the Parameters section.
Using sphinx.ext.napoleon attributes and methods are still generated after the Notes and Examples sections.
How to Reproduce
Environment Information
Sphinx extensions
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: