8000 BUG: Prevent autogenerated names clashing with given names · numpy/numpy@a4f435c · GitHub
[go: up one dir, main page]

Skip to content

Commit a4f435c

Browse files
committed
BUG: Prevent autogenerated names clashing with given names
1 parent 3c4545f commit a4f435c

File tree

2 files changed

+27
-27
lines changed

2 files changed

+27
-27
lines changed

numpy/core/_internal.py

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -470,25 +470,9 @@ def __dtype_from_pep3118(stream, is_subdtype):
470470
itemsize=0
471471
)
472472
offset = 0
473-
explicit_name = False
474-
this_explicit_name = False
475473
common_alignment = 1
476474
is_padding = False
477475

478-
dummy_name_index = [0]
479-
480-
481-
def next_dummy_name():
482-
dummy_name_index[0] += 1
483-
484-
def get_dummy_name():
485-
while True:
486-
name = 'f%d' % dummy_name_index[0]
487-
if name not in field_spec['names']:
488-
return name
489-
next_dummy_name()
490-
491-
492476
# Parse spec
493477
while stream:
494478
value = None
@@ -583,25 +567,19 @@ def get_dummy_name():
583567
value = dtype((value, shape))
584568

585569
# Field name
586-
this_explicit_name = False
587570
if stream.consume(':'):
588571
name = stream.consume_until(':')
589-
explicit_name = True
590-
this_explicit_name = True
591572
else:
592-
name = get_dummy_name()
573+
name = None
593574

594-
if not is_padding or this_explicit_name:
595-
if name in field_spec['names']:
575+
if not (is_padding and name is None):
576+
if name is not None and name in field_spec['names']:
596577
raise RuntimeError("Duplicate field name '%s' in PEP3118 format"
597578
% name)
598579
field_spec['names'].append(name)
599580
field_spec['formats'].append(value)
600581
field_spec['offsets'].append(offset)
601582

602-
if not this_explicit_name:
603-
next_dummy_name()
604-
605583
offset += value.itemsize
606584
offset += extra_offset
607585

@@ -612,18 +590,33 @@ def get_dummy_name():
612590
field_spec['itemsize'] += (-offset) % common_alignment
613591

614592
# Check if this was a simple 1-item type, and unwrap it
615-
if (len(field_spec['names']) == 1
593+
if (field_spec['names'] == [None]
616594
and field_spec['offsets'][0] == 0
617595
and field_spec['itemsize'] == field_spec['formats'][0].itemsize
618-
and not explicit_name
619596
and not is_subdtype):
620597
ret = field_spec['formats'][0]
621598
else:
599+
_fix_names(field_spec)
622600
ret = dtype(field_spec)
623601

624602
# Finished
625603
return ret, common_alignment
626604

605+
def _fix_names(field_spec):
606+
""" Replace names which are None with the next unused f%d name """
607+
names = field_spec['names']
608+
for i, name in enumerate(names):
609+
if name is not None:
610+
continue
611+
612+
j = 0
613+
while True:
614+
name = 'f{}'.format(j)
615+
if name not in names:
616+
break
617+
j = j + 1
618+
names[i] = name
619+
627620
def _add_trailing_padding(value, padding):
628621
"""Inject the specified number of padding bytes at the end of a dtype"""
629622
if value.fields is None:

numpy/core/tests/test_multiarray.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5927,6 +5927,13 @@ def test_field_order(self):
59275927
self._check("(0)I:a:f:b:", [('a', 'I', (0,)), ('b', 'f')])
59285928
self._check("(0)I:b:f:a:", [('b', 'I', (0,)), ('a', 'f')])
59295929

5930+
def test_unnamed_fields(self):
5931+
self._check('ii', [('f0', 'i'), ('f1', 'i')])
5932+
self._check('ii:f0:', [('f1', 'i'), ('f0', 'i')])
5933+
5934+
self._check('i', 'i')
5935+
self._check('i:f0:', [('f0', 'i')])
5936+
59305937
class TestNewBufferProtocol(object):
59315938
def _check_roundtrip(self, obj):
59325939
obj = np.asarray(obj)

0 commit comments

Comments
 (0)
0