Skip to content

Weird behavior of structured_to_unstructured on non-trivial dtypes #13333

Closed
@eric-wieser

Description

@eric-wieser

With the following helpers:

import numpy.lib.recfunctions as rfn
def subarray(dt, shape):
    return np.dtype((dt, shape))
def structured(*dts):
    return np.dtype([('x{}'.format(i), dt) for i, dt in enumerate(dts)])
def inspect(dt):
    arr = np.zeros((), dt)
    ret = rfn.structured_to_unstructured(arr)
    print(ret.shape, ret.dtype)

We can try a bunch of uses of structured_to_unstructured (added in #11526):

>>> inspect(structured(int, int))
(2,) int32  # obviously ok
>>> inspect(structured(int, structured(int, int)))
(3,) int32  # nested types are flattened, ok
>>> inspect(structured(int, subarray(int, 2)))
(3,) int32  # ok: 1 + 2
>>> inspect(structured(int, subarray(int, (2, 2))))
(5,) int32    # ok: 1 + 2*2

Here's where things start to go bad:

>>> inspect(structured(subarray(structured(int, int), 3)))
(3,) [('x0', '<i4'), ('x1', '<i4')] # bug?
>>> inspect(structured(subarray(subarray(int, 2), 2)))
(2, 2) int32  # bug
>>> inspect(structured(int))
() int32 # bug

(#13334)

>>> inspect(structured(int, subarray(subarray(int, 2), 2)))
TypeError: invalid type promotion
>>> inspect(structured())
    dts, counts, offsets = zip(*fields)
ValueError: not enough values to unpack (expected 3, got 0)

A lot of this behavior looks undesirable to me. @ahaldane, which cases were actually intended to be supported? Rather than locking ourselve into some of these weird constucts, we might want to raise an error for anything non-trivial.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions