Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PyArray_Scalar behaves like it is not supposed to in docs #9158

Open
vlasenkov opened this issue May 22, 2017 · 6 comments
Open

PyArray_Scalar behaves like it is not supposed to in docs #9158

vlasenkov opened this issue May 22, 2017 · 6 comments

Comments

@vlasenkov
Copy link

From here:

PyObject* PyArray_Scalar(void* data, PyArray_Descr* dtype, PyObject* itemsize)
Return an array scalar object of the given enumerated typenum and itemsize by copying from memory pointed to by data . If swap is nonzero then this function will byteswap the data if appropriate to the data-type because array scalars are always in correct machine-byte order.

But this C code:

static int64_t buffer[] = {7, 14};

static PyObject *
test(PyObject *self, PyObject *args) {
      PyObject *dtype;
      PyObject *is;
      PyArg_ParseTuple(args, "O!O!", &PyArrayDescr_Type, &dtype, &PyLong_Type, &is);
      PyObject *ret = PyArray_Scalar(buffer, (PyArray_Descr *)dtype, is);
      return ret;
}

static PyObject *
test2(PyObject *self, PyObject *args) {
      buffer[0] = 100;
      Py_RETURN_NONE;
}

Produces this (Numpy version: 1.12.0):

>>> dt = np.dtype([('a', np.int64),('b',np.int64)])
>>> a = test(dt, dt.itemsize)
>>> a
(7, 14)
>>> test2()
>>> a
(100, 14)

So, PyArray_Scalar does not copy memory. Is it a mistake in doc or a bug?

@k-kapp
Copy link
Contributor

k-kapp commented May 22, 2017

The relevant code section seems to be here. I managed to get the expected output (i.e., with a equal to (7, 14) after calling test2) by allocating memory via PyDataMem_NEW, and letting vobj->obval point to it, then doing a memcpy of size itemsize into vobj->obval from data. But the omission of copying data into the vobj structure seems to be intentional, since vobj->flags has the NPY_ARRAY_OWNDATA flag ANDed out, which according to my best guess, means that some other object must manage the data that was supposed to be copied. But I could very likely be wrong. Someone more experienced should look into this.

@vlasenkov
Copy link
Author

I could manage this fix, if someone confirmed that this is a bug.

@seberg
Copy link
Member

seberg commented May 24, 2017

Its an intentional bug though. If you would change this field assignments would break, such as:

arr[0]["asdf"] = 3

Now, this is a horrible way, and it should be arr["asdf"][0] = 3 for such reasons, but changing it requires a little more, and especially careful testing with the major downstream packages.

Ideally I would prefer if also void scalars were, at least by default, not mutable (which would be a start), but there are also problems involved here, if you put a large array as part of the dtype. In fact, then it all gets even hairier and I doubt there is an easy "right" here at all.

@vlasenkov
Copy link
Author

I think the documentation should be fixed at least.

@seberg
Copy link
Member

seberg commented May 24, 2017

Certainly

@mbengtanyi
Copy link

Hello, I would like to work on the documentation fix.

mbengtanyi added a commit to mbengtanyi/numpy that referenced this issue Apr 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants