Skip to content

Commit

Permalink
DEP: remove NPY_ARRAY_UPDATEIFCOPY, deprecated in 1.14 (#20589)
Browse files Browse the repository at this point in the history
* DEP: remove NPY_ARRAY_UPDATEIFCOPY, deprecated in 1.14

* remove more UPDATEIFCOPY

* typo: add missing comma

* remove a few more UPDATEIFCOPY

* Add release note

* remove UPDATEIFCOPY from comment (from review)
  • Loading branch information
mattip committed Dec 18, 2021
1 parent 0302205 commit bb95cf0
Show file tree
Hide file tree
Showing 31 changed files with 57 additions and 313 deletions.
7 changes: 7 additions & 0 deletions doc/release/upcoming_changes/20589.expired.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Remove deprecated ``NPY_ARRAY_UPDATEIFCOPY``
--------------------------------------------

The array flag ``UPDATEIFCOPY`` and enum ``NPY_ARRAY_UPDATEIFCOPY`` were
deprecated in 1.14. They were replaced by ``WRITEBACKIFCOPY`` which require
calling ``PyArray_ResoveWritebackIfCopy`` before the array is deallocated. Also
removed the associated (and deprecated) ``PyArray_XDECREF_ERR``.
56 changes: 13 additions & 43 deletions doc/source/reference/c-api/array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ and its sub-types).
your own memory, you should use the function :c:func:`PyArray_SetBaseObject`
to set the base to an object which owns the memory.
If the (deprecated) :c:data:`NPY_ARRAY_UPDATEIFCOPY` or the
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flags are set, it has a different
If the :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flag is set, it has a different
meaning, namely base is the array into which the current array will
be copied upon copy resolution. This overloading of the base property
for two functions is likely to change in a future version of NumPy.
Expand Down Expand Up @@ -237,8 +236,7 @@ From scratch
If *data* is not ``NULL``, then it is assumed to point to the memory
to be used for the array and the *flags* argument is used as the
new flags for the array (except the state of :c:data:`NPY_ARRAY_OWNDATA`,
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY` and :c:data:`NPY_ARRAY_UPDATEIFCOPY`
flags of the new array will be reset).
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flag of the new array will be reset).
In addition, if *data* is non-NULL, then *strides* can
also be provided. If *strides* is ``NULL``, then the array strides
Expand Down Expand Up @@ -487,13 +485,6 @@ From other objects
will be made writeable again. If *op* is not writeable to begin
with, or if it is not already an array, then an error is raised.
.. c:macro:: NPY_ARRAY_UPDATEIFCOPY
Deprecated. Use :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, which is similar.
This flag "automatically" copies the data back when the returned
array is deallocated, which is not supported in all python
implementations.
.. c:macro:: NPY_ARRAY_BEHAVED
:c:data:`NPY_ARRAY_ALIGNED` \| :c:data:`NPY_ARRAY_WRITEABLE`
Expand Down Expand Up @@ -550,14 +541,12 @@ From other objects
.. c:macro:: NPY_ARRAY_INOUT_ARRAY
:c:data:`NPY_ARRAY_C_CONTIGUOUS` \| :c:data:`NPY_ARRAY_WRITEABLE` \|
:c:data:`NPY_ARRAY_ALIGNED` \| :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` \|
:c:data:`NPY_ARRAY_UPDATEIFCOPY`
:c:data:`NPY_ARRAY_ALIGNED` \| :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`
.. c:macro:: NPY_ARRAY_INOUT_FARRAY
:c:data:`NPY_ARRAY_F_CONTIGUOUS` \| :c:data:`NPY_ARRAY_WRITEABLE` \|
:c:data:`NPY_ARRAY_ALIGNED` \| :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` \|
:c:data:`NPY_ARRAY_UPDATEIFCOPY`
:c:data:`NPY_ARRAY_ALIGNED` \| :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`
.. c:function:: int PyArray_GetArrayParamsFromObject( \
PyObject* op, PyArray_Descr* requested_dtype, npy_bool writeable, \
Expand Down Expand Up @@ -773,8 +762,7 @@ From other objects
:c:data:`NPY_ARRAY_C_CONTIGUOUS`, :c:data:`NPY_ARRAY_F_CONTIGUOUS`,
:c:data:`NPY_ARRAY_ALIGNED`, :c:data:`NPY_ARRAY_WRITEABLE`,
:c:data:`NPY_ARRAY_NOTSWAPPED`, :c:data:`NPY_ARRAY_ENSURECOPY`,
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, :c:data:`NPY_ARRAY_UPDATEIFCOPY`,
:c:data:`NPY_ARRAY_FORCECAST`, and
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, :c:data:`NPY_ARRAY_FORCECAST`, and
:c:data:`NPY_ARRAY_ENSUREARRAY`. Standard combinations of flags can also
be used:
Expand Down Expand Up @@ -1375,15 +1363,6 @@ Special functions for NPY_OBJECT
decrement all the items in the object array prior to calling this
function.
.. c:function:: int PyArray_SetUpdateIfCopyBase(PyArrayObject* arr, PyArrayObject* base)
Precondition: ``arr`` is a copy of ``base`` (though possibly with different
strides, ordering, etc.) Set the UPDATEIFCOPY flag and ``arr->base`` so
that when ``arr`` is destructed, it will copy any changes back to ``base``.
DEPRECATED, use :c:func:`PyArray_SetWritebackIfCopyBase`.
Returns 0 for success, -1 for failure.
.. c:function:: int PyArray_SetWritebackIfCopyBase(PyArrayObject* arr, PyArrayObject* base)
Precondition: ``arr`` is a copy of ``base`` (though possibly with different
Expand Down Expand Up @@ -1496,14 +1475,6 @@ of the constant names is deprecated in 1.7.
would have returned an error because :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`
would not have been possible.
.. c:macro:: NPY_ARRAY_UPDATEIFCOPY
A deprecated version of :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` which
depends upon ``dealloc`` to trigger the writeback. For backwards
compatibility, :c:func:`PyArray_ResolveWritebackIfCopy` is called at
``dealloc`` but relying
on that behavior is deprecated and not supported in PyPy.
:c:func:`PyArray_UpdateFlags` (obj, flags) will update the ``obj->flags``
for ``flags`` which can be any of :c:data:`NPY_ARRAY_C_CONTIGUOUS`,
:c:data:`NPY_ARRAY_F_CONTIGUOUS`, :c:data:`NPY_ARRAY_ALIGNED`, or
Expand Down Expand Up @@ -1575,8 +1546,7 @@ For all of these macros *arr* must be an instance of a (subclass of)
combinations of the possible flags an array can have:
:c:data:`NPY_ARRAY_C_CONTIGUOUS`, :c:data:`NPY_ARRAY_F_CONTIGUOUS`,
:c:data:`NPY_ARRAY_OWNDATA`, :c:data:`NPY_ARRAY_ALIGNED`,
:c:data:`NPY_ARRAY_WRITEABLE`, :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`,
:c:data:`NPY_ARRAY_UPDATEIFCOPY`.
:c:data:`NPY_ARRAY_WRITEABLE`, :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`.
.. c:function:: int PyArray_IS_C_CONTIGUOUS(PyObject *arr)
Expand Down Expand Up @@ -2765,7 +2735,7 @@ Array mapping is the machinery behind advanced indexing.
has memory overlap with any of the arrays in ``index`` and with
``extra_op``, and make copies as appropriate to avoid problems if the
input is modified during the iteration. ``iter->array`` may contain a
copied array (UPDATEIFCOPY/WRITEBACKIFCOPY set).
copied array (WRITEBACKIFCOPY set).
Array Scalars
-------------
Expand Down Expand Up @@ -3377,8 +3347,8 @@ Memory management
.. c:function:: int PyArray_ResolveWritebackIfCopy(PyArrayObject* obj)
If ``obj.flags`` has :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` or (deprecated)
:c:data:`NPY_ARRAY_UPDATEIFCOPY`, this function clears the flags, `DECREF` s
If ``obj.flags`` has :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, this function
clears the flags, `DECREF` s
`obj->base` and makes it writeable, and sets ``obj->base`` to NULL. It then
copies ``obj->data`` to `obj->base->data`, and returns the error state of
the copy operation. This is the opposite of
Expand Down Expand Up @@ -3609,8 +3579,8 @@ Miscellaneous Macros
.. c:function:: void PyArray_DiscardWritebackIfCopy(PyObject* obj)
If ``obj.flags`` has :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` or (deprecated)
:c:data:`NPY_ARRAY_UPDATEIFCOPY`, this function clears the flags, `DECREF` s
If ``obj.flags`` has :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, this function
clears the flags, `DECREF` s
`obj->base` and makes it writeable, and sets ``obj->base`` to NULL. In
contrast to :c:func:`PyArray_DiscardWritebackIfCopy` it makes no attempt
to copy the data from `obj->base` This undoes
Expand All @@ -3623,8 +3593,8 @@ Miscellaneous Macros
Deprecated in 1.14, use :c:func:`PyArray_DiscardWritebackIfCopy`
followed by ``Py_XDECREF``
DECREF's an array object which may have the (deprecated)
:c:data:`NPY_ARRAY_UPDATEIFCOPY` or :c:data:`NPY_ARRAY_WRITEBACKIFCOPY`
DECREF's an array object which may have the
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY`
flag set without causing the contents to be copied back into the
original array. Resets the :c:data:`NPY_ARRAY_WRITEABLE` flag on the base
object. This is useful for recovering from an error condition when
Expand Down
7 changes: 3 additions & 4 deletions doc/source/reference/c-api/types-and-structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,8 @@ PyArray_Type and PyArrayObject

- If this array does not own its own memory, then base points to the
Python object that owns it (perhaps another array object)
- If this array has the (deprecated) :c:data:`NPY_ARRAY_UPDATEIFCOPY` or
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flag set, then this array is a working
copy of a "misbehaved" array.
- If this array has the :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flag set,
then this array is a working copy of a "misbehaved" array.

When ``PyArray_ResolveWritebackIfCopy`` is called, the array pointed to
by base will be updated with the contents of this array.
Expand All @@ -169,7 +168,7 @@ PyArray_Type and PyArrayObject
interpreted. Possible flags are :c:data:`NPY_ARRAY_C_CONTIGUOUS`,
:c:data:`NPY_ARRAY_F_CONTIGUOUS`, :c:data:`NPY_ARRAY_OWNDATA`,
:c:data:`NPY_ARRAY_ALIGNED`, :c:data:`NPY_ARRAY_WRITEABLE`,
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY`, and :c:data:`NPY_ARRAY_UPDATEIFCOPY`.
:c:data:`NPY_ARRAY_WRITEBACKIFCOPY`.

.. c:member:: PyObject *weakreflist
Expand Down
5 changes: 2 additions & 3 deletions doc/source/user/c-info.how-to-extend.rst
Original file line number Diff line number Diff line change
Expand Up @@ -459,9 +459,8 @@ writeable). The syntax is
must be called before :c:func:`Py_DECREF` at
the end of the interface routine to write back the temporary data
into the original array passed in. Use
of the :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` or
:c:data:`NPY_ARRAY_UPDATEIFCOPY` flags requires that the input
object is already an array (because other objects cannot
of the :c:data:`NPY_ARRAY_WRITEBACKIFCOPY` flag requires that the
input object is already an array (because other objects cannot
be automatically updated in this fashion). If an error
occurs use :c:func:`PyArray_DiscardWritebackIfCopy` (obj) on an
array with these flags set. This will set the underlying base array
Expand Down
3 changes: 1 addition & 2 deletions numpy/__init__.cython-30.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ cdef extern from "numpy/arrayobject.h":
NPY_ALIGNED
NPY_NOTSWAPPED
NPY_WRITEABLE
NPY_UPDATEIFCOPY
NPY_ARR_HAS_DESCR

NPY_BEHAVED
Expand Down Expand Up @@ -165,7 +164,7 @@ cdef extern from "numpy/arrayobject.h":
NPY_ARRAY_ALIGNED
NPY_ARRAY_NOTSWAPPED
NPY_ARRAY_WRITEABLE
NPY_ARRAY_UPDATEIFCOPY
NPY_ARRAY_WRITEBACKIFCOPY

NPY_ARRAY_BEHAVED
NPY_ARRAY_BEHAVED_NS
Expand Down
3 changes: 1 addition & 2 deletions numpy/__init__.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ cdef extern from "numpy/arrayobject.h":
NPY_ALIGNED
NPY_NOTSWAPPED
NPY_WRITEABLE
NPY_UPDATEIFCOPY
NPY_ARR_HAS_DESCR

NPY_BEHAVED
Expand Down Expand Up @@ -162,7 +161,7 @@ cdef extern from "numpy/arrayobject.h":
NPY_ARRAY_ALIGNED
NPY_ARRAY_NOTSWAPPED
NPY_ARRAY_WRITEABLE
NPY_ARRAY_UPDATEIFCOPY
NPY_ARRAY_WRITEBACKIFCOPY

NPY_ARRAY_BEHAVED
NPY_ARRAY_BEHAVED_NS
Expand Down
18 changes: 4 additions & 14 deletions numpy/core/_add_newdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2477,11 +2477,6 @@
This array is a copy of some other array. The C-API function
PyArray_ResolveWritebackIfCopy must be called before deallocating
to the base array will be updated with the contents of this array.
UPDATEIFCOPY (U)
(Deprecated, use WRITEBACKIFCOPY) This array is a copy of some other array.
When this array is
deallocated, the base array will be updated with the contents of
this array.
FNC
F_CONTIGUOUS and not C_CONTIGUOUS.
FORC
Expand All @@ -2499,13 +2494,12 @@
or by using lowercased attribute names (as in ``a.flags.writeable``). Short flag
names are only supported in dictionary access.
Only the WRITEBACKIFCOPY, UPDATEIFCOPY, WRITEABLE, and ALIGNED flags can be
Only the WRITEBACKIFCOPY, WRITEABLE, and ALIGNED flags can be
changed by the user, via direct assignment to the attribute or dictionary
entry, or by calling `ndarray.setflags`.
The array flags cannot be set arbitrarily:
- UPDATEIFCOPY can only be set ``False``.
- WRITEBACKIFCOPY can only be set ``False``.
- ALIGNED can only be set ``True`` if the data is truly aligned.
- WRITEABLE can only be set ``True`` if the array owns its own memory
Expand Down Expand Up @@ -3907,13 +3901,13 @@
"""
a.setflags(write=None, align=None, uic=None)
Set array flags WRITEABLE, ALIGNED, (WRITEBACKIFCOPY and UPDATEIFCOPY),
Set array flags WRITEABLE, ALIGNED, WRITEBACKIFCOPY,
respectively.
These Boolean-valued flags affect how numpy interprets the memory
area used by `a` (see Notes below). The ALIGNED flag can only
be set to True if the data is actually aligned according to the type.
The WRITEBACKIFCOPY and (deprecated) UPDATEIFCOPY flags can never be set
The WRITEBACKIFCOPY and flag can never be set
to True. The flag WRITEABLE can only be set to True if the array owns its
own memory, or the ultimate owner of the memory exposes a writeable buffer
interface, or is a string. (The exception for string is made so that
Expand All @@ -3933,15 +3927,13 @@
Array flags provide information about how the memory area used
for the array is to be interpreted. There are 7 Boolean flags
in use, only four of which can be changed by the user:
WRITEBACKIFCOPY, UPDATEIFCOPY, WRITEABLE, and ALIGNED.
WRITEBACKIFCOPY, WRITEABLE, and ALIGNED.
WRITEABLE (W) the data area can be written to;
ALIGNED (A) the data and strides are aligned appropriately for the hardware
(as determined by the compiler);
UPDATEIFCOPY (U) (deprecated), replaced by WRITEBACKIFCOPY;
WRITEBACKIFCOPY (X) this array is a copy of some other array (referenced
by .base). When the C-API function PyArray_ResolveWritebackIfCopy is
called, the base array will be updated with the contents of this array.
Expand All @@ -3965,7 +3957,6 @@
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
>>> y.setflags(write=0, align=0)
>>> y.flags
C_CONTIGUOUS : True
Expand All @@ -3974,7 +3965,6 @@
WRITEABLE : False
ALIGNED : False
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
>>> y.setflags(uic=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Expand Down
2 changes: 0 additions & 2 deletions numpy/core/_asarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ def require(a, dtype=None, requirements=None, *, like=None):
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
>>> y = np.require(x, dtype=np.float32, requirements=['A', 'O', 'W', 'F'])
>>> y.flags
Expand All @@ -88,7 +87,6 @@ def require(a, dtype=None, requirements=None, *, like=None):
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
"""
if like is not None:
Expand Down
19 changes: 1 addition & 18 deletions numpy/core/include/numpy/ndarrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,16 @@ extern "C" {
(k)*PyArray_STRIDES(obj)[2] + \
(l)*PyArray_STRIDES(obj)[3]))

/* Move to arrayobject.c once PyArray_XDECREF_ERR is removed */
static NPY_INLINE void
PyArray_DiscardWritebackIfCopy(PyArrayObject *arr)
{
PyArrayObject_fields *fa = (PyArrayObject_fields *)arr;
if (fa && fa->base) {
if ((fa->flags & NPY_ARRAY_UPDATEIFCOPY) ||
(fa->flags & NPY_ARRAY_WRITEBACKIFCOPY)) {
if (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY) {
PyArray_ENABLEFLAGS((PyArrayObject*)fa->base, NPY_ARRAY_WRITEABLE);
Py_DECREF(fa->base);
fa->base = NULL;
PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
PyArray_CLEARFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY);
}
}
}
Expand Down Expand Up @@ -246,20 +243,6 @@ NPY_TITLE_KEY_check(PyObject *key, PyObject *value)
#define DEPRECATE(msg) PyErr_WarnEx(PyExc_DeprecationWarning,msg,1)
#define DEPRECATE_FUTUREWARNING(msg) PyErr_WarnEx(PyExc_FutureWarning,msg,1)

#if !defined(NPY_NO_DEPRECATED_API) || \
(NPY_NO_DEPRECATED_API < NPY_1_14_API_VERSION)
static NPY_INLINE void
PyArray_XDECREF_ERR(PyArrayObject *arr)
{
/* 2017-Nov-10 1.14 */
DEPRECATE("PyArray_XDECREF_ERR is deprecated, call "
"PyArray_DiscardWritebackIfCopy then Py_XDECREF instead");
PyArray_DiscardWritebackIfCopy(arr);
Py_XDECREF(arr);
}
#endif


#ifdef __cplusplus
}
#endif
Expand Down
7 changes: 2 additions & 5 deletions numpy/core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,6 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
* This flag may be requested in constructor functions.
* This flag may be tested for in PyArray_FLAGS(arr).
*/
#define NPY_ARRAY_UPDATEIFCOPY 0x1000 /* Deprecated in 1.14 */
#define NPY_ARRAY_WRITEBACKIFCOPY 0x2000

/*
Expand Down Expand Up @@ -965,14 +964,12 @@ typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
#define NPY_ARRAY_DEFAULT (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_IN_ARRAY (NPY_ARRAY_CARRAY_RO)
#define NPY_ARRAY_OUT_ARRAY (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_INOUT_ARRAY (NPY_ARRAY_CARRAY | \
NPY_ARRAY_UPDATEIFCOPY)
#define NPY_ARRAY_INOUT_ARRAY (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_INOUT_ARRAY2 (NPY_ARRAY_CARRAY | \
NPY_ARRAY_WRITEBACKIFCOPY)
#define NPY_ARRAY_IN_FARRAY (NPY_ARRAY_FARRAY_RO)
#define NPY_ARRAY_OUT_FARRAY (NPY_ARRAY_FARRAY)
#define NPY_ARRAY_INOUT_FARRAY (NPY_ARRAY_FARRAY | \
NPY_ARRAY_UPDATEIFCOPY)
#define NPY_ARRAY_INOUT_FARRAY (NPY_ARRAY_FARRAY)
#define NPY_ARRAY_INOUT_FARRAY2 (NPY_ARRAY_FARRAY | \
NPY_ARRAY_WRITEBACKIFCOPY)

Expand Down
1 change: 0 additions & 1 deletion numpy/core/include/numpy/noprefix.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@
#define ALIGNED NPY_ALIGNED
#define NOTSWAPPED NPY_NOTSWAPPED
#define WRITEABLE NPY_WRITEABLE
#define UPDATEIFCOPY NPY_UPDATEIFCOPY
#define WRITEBACKIFCOPY NPY_ARRAY_WRITEBACKIFCOPY
#define ARR_HAS_DESCR NPY_ARR_HAS_DESCR
#define BEHAVED NPY_BEHAVED
Expand Down
1 change: 0 additions & 1 deletion numpy/core/include/numpy/npy_1_7_deprecated_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
#define NPY_ALIGNED NPY_ARRAY_ALIGNED
#define NPY_NOTSWAPPED NPY_ARRAY_NOTSWAPPED
#define NPY_WRITEABLE NPY_ARRAY_WRITEABLE
#define NPY_UPDATEIFCOPY NPY_ARRAY_UPDATEIFCOPY
#define NPY_BEHAVED NPY_ARRAY_BEHAVED
#define NPY_BEHAVED_NS NPY_ARRAY_BEHAVED_NS
#define NPY_CARRAY NPY_ARRAY_CARRAY
Expand Down
Loading

0 comments on commit bb95cf0

Please sign in to comment.