Source code for majis.misc.csv
"""CSV miscellaneous module."""
from planetary_coverage.events import Event, EventsDict, EventsList, EventWindow
from .time import fmt_datetime
CSV_TIME_REL_KEYS = {
't_start': ['OBS_START', 'OBS_START_REL'],
't_end': ['OBS_END', 'OBS_END_REL'],
}
[docs]
def get_header(
blocks: list[list | dict] | EventsList | EventsDict,
ref: str | dict | None = None,
) -> list:
"""Get CSV header.
The keys are unique and ordered with the following rules:
- If `OBS_NAME` is present, it will be placed first.
- `t_start` and `t_end` are required and replaced by `OBS_START`
and `OBS_END` and placed after `OBS_NAME` (if present).
- if `ref` time is provided `OBS_START_REL` and `OBS_END_REL`
are appended after `OBS_START` and `OBS_END`.
- `COMMENTS` is present, it will always put last.
"""
keys = dict.fromkeys(key for block in blocks for key in block)
first, last = [], []
if 'OBS_NAME' in keys:
keys.pop('OBS_NAME')
first.append('OBS_NAME')
if 't_start' in keys:
keys.pop('t_start')
first.append('OBS_START')
else:
raise KeyError('Missing `t_start` keyword.')
if 't_end' in keys:
keys.pop('t_end')
first.append('OBS_END')
else:
raise KeyError('Missing `t_end` keyword.')
if ref:
first.append('OBS_START_REL')
first.append('OBS_END_REL')
if 'COMMENTS' in keys:
keys.pop('COMMENTS')
last.append('COMMENTS')
return first + list(keys) + last
[docs]
def get_value(
block: dict | Event | EventWindow,
key: str,
ref: str | None = None,
) -> str:
"""Format block value.
This method extract the block value for a given property
and re-format the datetime if necessary.
Comments values are escaped with double quotes (`"..."`).
"""
if key == 'OBS_START':
return fmt_datetime(block['t_start'])
if key in ['OBS_START', 'OBS_END']:
return fmt_datetime(block['t_end'])
if key == 'OBS_START_REL' and ref:
return fmt_datetime(block['t_start'], ref=ref)
if key == 'OBS_END_REL' and ref:
return fmt_datetime(block['t_end'], ref=ref)
value = str(block.get(key, ''))
if key == 'COMMENTS':
return f'"{value}"'
return value
[docs]
def fmt_csv(
blocks: dict | EventsList | EventsDict,
ref: str | None = None,
sep: str = ';',
) -> str:
"""Format CSV format."""
# Get unique header keys (ordered)
header = get_header(blocks, ref=ref)
# Create rows values with separator
rows = [
sep.join(get_value(block, key, ref=ref) for key in header) for block in blocks
]
# Merge header and rows
return ['#' + sep.join(header)] + rows