Summary
get_tab2_record (src/endf/records.py) reads its interpolation pairs with the built-in int(), while the otherwise identical loop in get_tab1_record uses int_endf().
https://github.com/shimwell/endf-python/blob/main/src/endf/records.py#L222-L229
for _ in range((n_regions - 1)//3 + 1):
line = file_obj.readline()
to_read = min(3, n_regions - m)
for _ in range(to_read):
breakpoints[m] = int(line[0:11]) # <-- int
interpolation[m] = int(line[11:22]) # <-- int
line = line[22:]
m += 1
against get_tab1_record:
breakpoints[m] = int_endf(line[0:11])
interpolation[m] = int_endf(line[11:22])
Effect
int_endf exists because the format permits an integer to be written as an all-blank field, meaning zero:
def int_endf(s: str) -> int:
return 0 if s.isspace() else int(s)
So a TAB2 record with a blank NBT or INT field raises ValueError: invalid literal for int() with base 10 where the equivalent TAB1 record reads it as 0. TAB2 records appear in MF4, MF5 and MF6, so this is reachable from ordinary evaluations — it just depends on an evaluator leaving a field blank rather than writing an explicit zero.
Suggested fix
Use int_endf in both places, matching get_tab1_record.
Notes
The to_read inner loop also rebinds line = line[22:] rather than indexing at an offset, which is fine but makes the two functions harder to compare; using the same offset arithmetic as get_tab1_record would make the divergence above obvious.
Found while porting the reader to Rust. The port uses the lenient reading in both records, since that is what the format specifies and what TAB1 already does — this is the one place the port deliberately differs from current behaviour, and it only differs on input that currently raises.
Summary
get_tab2_record(src/endf/records.py) reads its interpolation pairs with the built-inint(), while the otherwise identical loop inget_tab1_recordusesint_endf().https://github.com/shimwell/endf-python/blob/main/src/endf/records.py#L222-L229
against
get_tab1_record:Effect
int_endfexists because the format permits an integer to be written as an all-blank field, meaning zero:So a TAB2 record with a blank NBT or INT field raises
ValueError: invalid literal for int() with base 10where the equivalent TAB1 record reads it as 0. TAB2 records appear in MF4, MF5 and MF6, so this is reachable from ordinary evaluations — it just depends on an evaluator leaving a field blank rather than writing an explicit zero.Suggested fix
Use
int_endfin both places, matchingget_tab1_record.Notes
The
to_readinner loop also rebindsline = line[22:]rather than indexing at an offset, which is fine but makes the two functions harder to compare; using the same offset arithmetic asget_tab1_recordwould make the divergence above obvious.Found while porting the reader to Rust. The port uses the lenient reading in both records, since that is what the format specifies and what TAB1 already does — this is the one place the port deliberately differs from current behaviour, and it only differs on input that currently raises.