Skip to content

Commit e16ad3b

Browse files
committed
MNT: respond to review comments
1 parent a914726 commit e16ad3b

File tree

7 files changed

+50
-40
lines changed

7 files changed

+50
-40
lines changed

numpy/_core/src/multiarray/convert_datatype.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,35 @@ PyArray_CanCastTo(PyArray_Descr *from, PyArray_Descr *to)
651651
}
652652

653653

654+
/*
655+
* This function returns true if the two types can be safely cast at
656+
* *minimum_safety* casting level. Sets the *view_offset* if that is set
657+
* for the cast. If ignore_error is set, the error indicator is cleared
658+
* if there are any errors in cast setup and returns false, otherwise
659+
* the error indicator is left set and returns -1.
660+
*/
661+
NPY_NO_EXPORT npy_intp
662+
PyArray_SafeCast(PyArray_Descr *type1, PyArray_Descr *type2,
663+
npy_intp* view_offset, NPY_CASTING minimum_safety,
664+
npy_intp ignore_error)
665+
{
666+
if (type1 == type2) {
667+
*view_offset = 0;
668+
return 1;
669+
}
670+
671+
NPY_CASTING safety = PyArray_GetCastInfo(type1, type2, NULL, view_offset);
672+
if (safety < 0) {
673+
if (ignore_error) {
674+
PyErr_Clear();
675+
return 0;
676+
}
677+
return -1;
678+
}
679+
return PyArray_MinCastSafety(safety, minimum_safety) == minimum_safety;
680+
}
681+
682+
654683
/* Provides an ordering for the dtype 'kind' character codes */
655684
NPY_NO_EXPORT int
656685
dtype_kind_to_ordering(char kind)

numpy/_core/src/multiarray/convert_datatype.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ PyArray_GetCastInfo(
102102
PyArray_Descr *from, PyArray_Descr *to, PyArray_DTypeMeta *to_dtype,
103103
npy_intp *view_offset);
104104

105+
NPY_NO_EXPORT npy_intp
106+
PyArray_SafeCast(PyArray_Descr *type1, PyArray_Descr *type2,
107+
npy_intp* view_offset, NPY_CASTING minimum_safety,
108+
npy_intp ignore_errors);
109+
105110
NPY_NO_EXPORT int
106111
PyArray_CheckCastSafety(NPY_CASTING casting,
107112
PyArray_Descr *from, PyArray_Descr *to, PyArray_DTypeMeta *to_dtype);

numpy/_core/src/multiarray/ctors.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,12 +1908,10 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
19081908
}
19091909

19101910
arrflags = PyArray_FLAGS(arr);
1911-
npy_intp view_offset;
1912-
npy_intp is_safe = PyArray_SafeCast(oldtype, newtype, &view_offset, NPY_NO_CASTING, 1);
1913-
npy_intp view_safe = (is_safe && (view_offset == 0));
19141911

1915-
/* If a guaranteed copy was requested */
1916-
copy = (flags & NPY_ARRAY_ENSURECOPY) ||
1912+
1913+
copy = /* If a guaranteed copy was requested */
1914+
(flags & NPY_ARRAY_ENSURECOPY) ||
19171915
/* If C contiguous was requested, and arr is not */
19181916
((flags & NPY_ARRAY_C_CONTIGUOUS) &&
19191917
(!(arrflags & NPY_ARRAY_C_CONTIGUOUS))) ||
@@ -1925,8 +1923,13 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
19251923
(!(arrflags & NPY_ARRAY_F_CONTIGUOUS))) ||
19261924
/* If a writeable array was requested, and arr is not */
19271925
((flags & NPY_ARRAY_WRITEABLE) &&
1928-
(!(arrflags & NPY_ARRAY_WRITEABLE))) ||
1929-
!view_safe;
1926+
(!(arrflags & NPY_ARRAY_WRITEABLE)));
1927+
1928+
if (!copy) {
1929+
npy_intp view_offset;
1930+
npy_intp is_safe = PyArray_SafeCast(oldtype, newtype, &view_offset, NPY_NO_CASTING, 1);
1931+
copy = copy || !(is_safe && (view_offset == 0));
1932+
}
19301933

19311934
if (copy) {
19321935
if (flags & NPY_ARRAY_ENSURENOCOPY ) {

numpy/_core/src/multiarray/multiarraymodule.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,33 +1464,6 @@ PyArray_EquivTypes(PyArray_Descr *type1, PyArray_Descr *type2)
14641464
}
14651465

14661466

1467-
/*
1468-
* This function returns true if the two types can be safely cast at
1469-
* *minimum_safety* casting level. Sets the view_offset if that is set
1470-
* for the cast. If ignore_error is 1, errors in cast setup are ignored.
1471-
*/
1472-
NPY_NO_EXPORT npy_intp
1473-
PyArray_SafeCast(PyArray_Descr *type1, PyArray_Descr *type2,
1474-
npy_intp* view_offset, NPY_CASTING minimum_safety,
1475-
npy_intp ignore_error)
1476-
{
1477-
if (type1 == type2) {
1478-
*view_offset = 0;
1479-
return 1;
1480-
}
1481-
1482-
NPY_CASTING safety = PyArray_GetCastInfo(type1, type2, NULL, view_offset);
1483-
if (safety < 0) {
1484-
if (ignore_error) {
1485-
PyErr_Clear();
1486-
return 0;
1487-
}
1488-
return -1;
1489-
}
1490-
return PyArray_MinCastSafety(safety, minimum_safety) == minimum_safety;
1491-
}
1492-
1493-
14941467
/*NUMPY_API*/
14951468
NPY_NO_EXPORT unsigned char
14961469
PyArray_EquivTypenums(int typenum1, int typenum2)

numpy/_core/src/multiarray/multiarraymodule.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,4 @@ NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_convert_if_no_array;
2121
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_cpu;
2222
NPY_VISIBILITY_HIDDEN extern PyObject * npy_ma_str_array_err_msg_substr;
2323

24-
NPY_NO_EXPORT npy_intp
25-
PyArray_SafeCast(PyArray_Descr *type1, PyArray_Descr *type2,
26-
npy_intp* view_offset, NPY_CASTING minimum_safety,
27-
npy_intp ignore_errors);
28-
2924
#endif /* NUMPY_CORE_SRC_MULTIARRAY_MULTIARRAYMODULE_H_ */

numpy/_core/src/umath/ufunc_object.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
#include "legacy_array_method.h"
6363
#include "abstractdtypes.h"
6464
#include "mapping.h"
65-
#include "multiarraymodule.h"
6665

6766
/* TODO: Only for `NpyIter_GetTransferFlags` until it is public */
6867
#define NPY_ITERATOR_IMPLEMENTATION_CODE

numpy/_core/tests/test_stringdtype.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,21 @@ def test_creation_functions():
460460

461461
def test_create_with_copy_none(string_list):
462462
arr = np.array(string_list, dtype=StringDType())
463+
# create another stringdtype array with an arena that has a different
464+
# in-memory layout than the first array
463465
arr_rev = np.array(string_list[::-1], dtype=StringDType())
464466

467+
# this should create a copy and the resulting array
468+
# shouldn't share an allocator or arena with arr_rev, despite
469+
# explicitly passing arr_rev.dtype
465470
arr_copy = np.array(arr, copy=None, dtype=arr_rev.dtype)
466471
np.testing.assert_array_equal(arr, arr_copy)
467472
assert arr_copy.base is None
468473

469474
with pytest.raises(ValueError, match="Unable to avoid copy"):
470475
np.array(arr, copy=False, dtype=arr_rev.dtype)
471476

477+
# because we're using arr's dtype instance, the view is safe
472478
arr_view = np.array(arr, copy=None, dtype=arr.dtype)
473479
np.testing.assert_array_equal(arr, arr)
474480
np.testing.assert_array_equal(arr_view[::-1], arr_rev)

0 commit comments

Comments
 (0)