Skip to content
Snippets Groups Projects
Verified Commit e10c4cd5 authored by Owen Graham's avatar Owen Graham
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
*.py[cod]
__pycache__/
*.so
*~
"""Parse AMRC's ASCII columnar data."""
from collections import namedtuple
Column = namedtuple('Column', ('name', 'type', 'width'))
class DataSpec:
"""Details about how to parse an aligned data file.
Arguments:
cols (Columns): columns' name, type, and width
leading (int): number of leading lines to ignore
"""
def __init__(self, cols, leading=0):
self.cols = cols
self.leading = leading
self.namedtuple = namedtuple('row', (col.name for col in cols))
class Columns(tuple):
"""Details about how to parse aligned data."""
def __new__(cls, *data):
columns = map(Column._make, data)
return tuple.__new__(cls, columns)
def __repr__(self):
contents = ', '.join(map(repr, self))
return f'{type(self).__name__}({contents})'
def parse_data(stream, dataspec):
"""Read lines from `stream` and yield `namedtuple` data."""
for line_num, line in enumerate(stream, start=1):
if line_num <= dataspec.leading:
continue
row = parse_line(line, dataspec, line_num=line_num)
yield dataspec.namedtuple._make(row)
def parse_line(line, dataspec, line_num=None):
"""Yield data from the line."""
start = end = 0
for col_num, col in enumerate(dataspec.cols, start=1):
end += col.width
cell = line[start:end].strip()
if cell:
try:
yield col.type(cell)
except ValueError as err:
where = f'data column {col_num}'
if line_num is not None:
where = f'line {line_num}, {where}'
message = f'Unexpected data format at {where}: {cell!r}'
raise ValueError(message) from err
else:
yield None
start = end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment