annie.parsers.csvmeta¶
Generic table metadata parser for label / protagonist sources (domain).
Unlike the fixed 17-column detection schema (annie.parsers.base), a label
table has an arbitrary shape: the user picks which column joins to the video id (the
key column) and which columns to surface as tags/filters (the value
columns). This module reads headers, suggests a key column by matching values
against the known video stems, and builds a key -> {column: value} map.
A table is a CSV file or one worksheet of an Excel workbook: every reader takes an
optional sheet and hands workbooks to annie.parsers.workbook, so callers
never care which format they read.
When a key repeats, an explicit order column decides which row counts (e.g. the
newest timestamp); see order_rows() and duplicate_report().
Classes¶
How a table's key column repeats, for the Dataset tab's warning. |
|
A proposed way to join a table to the videos. |
Functions¶
|
Return the column names of a table (its header row). |
|
Read a table into column-keyed dict rows (CSV: BOM- and CRLF-tolerant). |
|
Count data rows in a table (excludes the header), cheaply. |
|
Guess which column joins the CSV to videos. |
|
Build a |
|
Return |
|
Report the repeated keys of a table and which of them the order can't separate. |
|
Propose the (id column, target) pair whose values overlap the most. |
|
Prefill for a tag name: the header on one line, cut at a word within |
|
Return the distinct non-empty values of one column, in first-seen order. |
|
Return the sorted distinct non-empty values of |
Module Contents¶
- annie.parsers.csvmeta.read_header(path: str | pathlib.Path, sheet: str | None = None) list[str][source]¶
Return the column names of a table (its header row).
- Parameters:
path – Path to the CSV file or workbook.
sheet – The worksheet of a workbook (
None: the first); ignored for a CSV.
- Returns:
The header column names in order, or an empty list if the file is empty or missing.
- annie.parsers.csvmeta.read_rows(path: str | pathlib.Path, sheet: str | None = None) list[dict[str, str]][source]¶
Read a table into column-keyed dict rows (CSV: BOM- and CRLF-tolerant).
- Parameters:
path – Path to the CSV file or workbook.
sheet – The worksheet of a workbook (
None: the first); ignored for a CSV.
- Returns:
One dict per data row, keyed by column name. Empty if missing.
- annie.parsers.csvmeta.count_rows(path: str | pathlib.Path, sheet: str | None = None) int[source]¶
Count data rows in a table (excludes the header), cheaply.
- Parameters:
path – Path to the CSV file or workbook.
sheet – The worksheet of a workbook (
None: the first); ignored for a CSV.
- Returns:
The number of data rows, or
0if missing/empty.
- annie.parsers.csvmeta.suggest_key_column(path: str | pathlib.Path, video_stems: set[str] | None = None, *, sample: int = 500, sheet: str | None = None) str | None[source]¶
Guess which column joins the CSV to videos.
Scores each column by the fraction of its sampled values found in
video_stems; the best non-zero column wins. With no stems (or no match), falls back to the first header that looks like an id (see_KEY_HINTS), else the first column.- Parameters:
path – Path to the CSV file.
video_stems – Known video stems to match against, or
None.sample – Maximum number of rows to inspect.
sheet – The worksheet of a workbook (
None: the first); ignored for a CSV.
- Returns:
The suggested key-column name, or
Noneif the file has no header.
- annie.parsers.csvmeta.load_value_map(path: str | pathlib.Path, key_column: str, value_columns: tuple[str, ...] | list[str], *, sheet: str | None = None, order_column: str | None = None, descending: bool = True) dict[str, dict[str, str]][source]¶
Build a
key -> {value_column: value}mapping from a table.- Parameters:
path – Path to the CSV file or workbook.
key_column – The column whose value identifies the video (the join key).
value_columns – The columns to carry into each entry.
sheet – The worksheet of a workbook (
None: the first); ignored for a CSV.order_column – Decides which row counts when a key repeats: rows are ordered by it (see
order_rows()) and the first row per key wins.descending – Order direction;
Trueputs the largest / newest value first.
- Returns:
Mapping from the (stripped) key value to a dict of the selected column values, in winning-row order. Rows with an empty key are skipped. Without an
order_columna repeated key keeps its last row (the historical rule; the Dataset tab requires an order column whenever a key repeats).
- annie.parsers.csvmeta.order_rows(rows: list[dict[str, str]], column: str, *, descending: bool) list[dict[str, str]][source]¶
Return
rowssorted bycolumn, stably, with empty values always last.The column compares numerically when every non-empty value is a number (
9 < 10), otherwise as text — which also orders ISO dates and timestamps chronologically, the formannie.parsers.workbookgives Excel dates. Rows with equal values keep their file order, so the result is always deterministic.- Parameters:
rows – Dict rows as returned by
read_rows().column – The column to order by.
descending –
Truefor largest / newest first.
- Returns:
A new, ordered list (the input is not modified).
- class annie.parsers.csvmeta.DuplicateReport[source]¶
How a table’s key column repeats, for the Dataset tab’s warning.
- duplicated¶
Keys that appear on more than one row, in first-seen order.
- ties¶
Duplicated keys whose two leading rows (after ordering) share the same order value, so only file order separates them. Every duplicated key is a tie when no order column is given.
- annie.parsers.csvmeta.duplicate_report(rows: list[dict[str, str]], key_column: str, order_column: str | None = None, *, descending: bool = True) DuplicateReport[source]¶
Report the repeated keys of a table and which of them the order can’t separate.
- Parameters:
rows – Dict rows as returned by
read_rows().key_column – The join-key column.
order_column – The column chosen to resolve repeats, or
None.descending – The chosen order direction.
- Returns:
- class annie.parsers.csvmeta.JoinSuggestion[source]¶
A proposed way to join a table to the videos.
- column¶
The table column holding the ids.
- target¶
What the ids match: a target name passed to
suggest_join().
- matched¶
How many distinct ids of that column the target contains.
- annie.parsers.csvmeta.suggest_join(rows: list[dict[str, str]], header: list[str], targets: dict[str, set[str]], *, sample: int = 500) JoinSuggestion | None[source]¶
Propose the (id column, target) pair whose values overlap the most.
A target is anything ids can match: all video ids, or the values of one nested- layout path field such as
{subject}. Ties go to the earlier column, then the earlier target, so the first target (the video id) wins when both fit equally.- Parameters:
rows – Dict rows as returned by
read_rows().header – The table’s column names, in order.
targets – Target name to the set of values it offers.
sample – Maximum number of rows to inspect.
- Returns:
The best
JoinSuggestion, orNonewhen no column matches anything.
- annie.parsers.csvmeta.short_name(header: str, limit: int = _SHORT_NAME_LIMIT) str[source]¶
Prefill for a tag name: the header on one line, cut at a word within
limit.- Parameters:
header – The column header (may be a long, multi-line question).
limit – Maximum length of the result.
- Returns:
The header with whitespace collapsed; when longer than
limit, cut back to the last whole word and marked with….
- annie.parsers.csvmeta.distinct_column_values(rows: list[dict[str, str]], column: str) list[str][source]¶
Return the distinct non-empty values of one column, in first-seen order.
Used by the Browse id-list filter: a CSV supplies the set of video ids to keep, and the order is preserved so the preview shows them as the file lists them.
- Parameters:
rows – Dict rows as returned by
read_rows().column – The column to collect.
- Returns:
The distinct stripped values of
column, empties excluded.
- annie.parsers.csvmeta.distinct_values(value_map: dict[str, dict[str, str]], column: str) list[str][source]¶
Return the sorted distinct non-empty values of
columnacross a map.- Parameters:
value_map – A map from
load_value_map().column – The value column to collect.
- Returns:
Sorted distinct values, empties excluded.