8000 BUG: Fix misuse of .names and .fields in various places (backport 14290 to 1.17) by eric-wieser · Pull Request #14339 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: Fix misuse of .names and .fields in various places (backport 14290 to 1.17) #14339

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

Merged
merged 13 commits into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
BUG: Make np.record work on structured fields with no fields
This replaces some more uses of `bool(dt.fields)` and `bool(dt.names)` with `dt.names is not None`.

`dt.fields is not None` would have worked too, but checking `.names` is more prevalent elsewhere
  • Loading branch information
eric-wieser committed Aug 19, 2019
commit 5fbce6d395a6bfd1ec25022dcee4eef8c5bbad17
14 changes: 7 additions & 7 deletions numpy/core/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def __getattribute__(self, attr):
except AttributeError:
#happens if field is Object type
return obj
if dt.fields:
if dt.names is not None:
return obj.view((self.__class__, obj.dtype.fields))
return obj
else:
Expand All @@ -279,7 +279,7 @@ def __getitem__(self, indx):
obj = nt.void.__getitem__(self, indx)

# copy behavior of record.__getattribute__,
if isinstance(obj, nt.void) and obj.dtype.fields:
if isinstance(obj, nt.void) and obj.dtype.names is not None:
return obj.view((self.__class__, obj.dtype.fields))
else:
# return a single element
Expand Down Expand Up @@ -431,7 +431,7 @@ def __new__(subtype, shape, dtype=None, buf=None, offset=0, strides=None,
return self

def __array_finalize__(self, obj):
if self.dtype.type is not record and self.dtype.fields:
if self.dtype.type is not record and self.dtype.names is not None:
# if self.dtype is not np.record, invoke __setattr__ which will
# convert it to a record if it is a void dtype.
self.dtype = self.dtype
Expand Down Expand Up @@ -459,7 +459,7 @@ def __getattribute__(self, attr):
# with void type convert it to the same dtype.type (eg to preserve
# numpy.record type if present), since nested structured fields do not
# inherit type. Don't do this for non-void structures though.
if obj.dtype.fields:
if obj.dtype.names is not None:
if issubclass(obj.dtype.type, nt.void):
return obj.view(dtype=(self.dtype.type, obj.dtype))
return obj
Expand All @@ -474,7 +474,7 @@ def __setattr__(self, attr, val):

# Automatically convert (void) structured types to records
# (but not non-void structures, subarrays, or non-structured voids)
if attr == 'dtype' and issubclass(val.type, nt.void) and val.fields:
if attr == 'dtype' and issubclass(val.type, nt.void) and val.names is not None:
8000 val = sb.dtype((record, val))

newattr = attr not in self.__dict__
Expand Down Expand Up @@ -508,7 +508,7 @@ def __getitem__(self, indx):
# copy behavior of getattr, except that here
# we might also be returning a single element
if isinstance(obj, ndarray):
if obj.dtype.fields:
if obj.dtype.names is not None:
obj = obj.view(type(self))
if issubclass(obj.dtype.type, nt.void):
return obj.view(dtype=(self.dtype.type, obj.dtype))
Expand Down Expand Up @@ -564,7 +564,7 @@ def field(self, attr, val=None):

if val is None:
obj = self.getfield(*res)
if obj.dtype.fields:
if obj.dtype.names is not None:
return obj
return obj.view(ndarray)
else:
Expand Down
27 changes: 27 additions & 0 deletions numpy/core/tests/test_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,33 @@ def test_missing_field(self):
arr = np.zeros((3,), dtype=[('x', int), ('y', int)])
assert_raises(ValueError, lambda: arr[['nofield']])

@pytest.mark.parametrize('nfields', [0, 1, 2])
def test_assign_dtype_attribute(self, nfields):
dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
data = np.zeros(3, dt).view(np.recarray)

# the original and resulting dtypes differ on whether they are records
assert data.dtype.type == np.record
assert dt.type != np.record

# ensure that the dtype remains a record even when assigned
data.dtype = dt
assert data.dtype.type == np.record

@pytest.mark.parametrize('nfields', [0, 1, 2])
def test_nested_fields_are_records(self, nfields):
""" Test that nested structured types are treated as records too """
dt = np.dtype([('a', np.uint8), ('b', np.uint8), ('c', np.uint8)][:nfields])
dt_outer = np.dtype([('inner', dt)])

data = np.zeros(3, dt_outer).view(np.recarray)
assert isinstance(data, np.recarray)
assert isinstance(data['inner'], np.recarray)

data0 = data[0]
assert isinstance(data0, np.record)
assert isinstance(data0['inner'], np.record)


def test_find_duplicate():
l1 = [1, 2, 3, 4, 5, 6]
Expand Down
0