rows_from_file() ignores ignore_extras= and extras_key= for anything that isn't Format.CSV

オープン 初心者向け
#892 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 3 日以内に返信

@feiiiiii5 がすでに取り組んでいます。

2026年9月30日 から。

  • #893 @feiiiiii5 による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
88/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
tooling

調査の方向性

sqlite_utils/utils.py の rows_from_file() から始めて、tests/test_rows_from_file.py を確認します。特に、44 行目にある既存の CSV テストを確認してください。rows_from_file のテストを実行してから、明示的に言及されている TSV および自動検出されるパスをカバーし、デフォルトの RowError 動作を維持してください。ignore_extras と extras_key がそれらのパスで一貫して機能し、文書化されたデフォルトを変更しないことが完了の条件です。

索引モデルが issue の本文から書いたものです。

説明

rows_from_file() ignores ignore_extras= and extras_key= for anything that isn't explicitly format=Format.CSV.

The docstring says:

If a CSV or TSV file includes rows with more fields than are declared in the header a sqlite_utils.utils.RowError exception will be raised when you loop over the generator.

You can instead ignore the extra data by passing ignore_extras=True.

Or pass extras_key="rest" to put those additional values in a list in a key called rest.

In practice those two options only work for format=Format.CSV. For TSV — which the docstring names explicitly — and for the auto-detected path (format omitted) they are silently discarded, and the caller's own explicit request is contradicted by a RowError.

Both branches that recurse into the CSV branch call rows_from_file() without forwarding the two arguments, so the inner call uses its own defaults (ignore_extras=False, extras_key=None) and raises before the outer _extra_key_strategy() wrapper — which is dead code — ever sees the row:

>>> from io import BytesIO
>>> from sqlite_utils.utils import rows_from_file, Format
>>> rows, _ = rows_from_file(
...     BytesIO(b"id\tname\r\n1\tCleo\toops"),
...     format=Format.TSV,
...     ignore_extras=True,
... )
>>> list(rows)
Traceback (most recent call last):
  ...
sqlite_utils.utils.RowError: Row {'id': '1', 'name': 'Cleo'} contained these extra values: ['oops']

The same happens with extras_key="_rest":

>>> rows, _ = rows_from_file(
...     BytesIO(b"id\tname\r\n1\tCleo\toops"),
...     format=Format.TSV,
...     extras_key="_rest",
... )
>>> list(rows)
Traceback (most recent call last):
  ...
sqlite_utils.utils.RowError: Row {'id': '1', 'name': 'Cleo'} contained these extra values: ['oops']

With no options passed the behaviour is correct and should not change — RowError is still raised, as documented.

git log -S"_extra_key_strategy" points at d379f43 ("rows_from_file(... ignore_extras: bool, restkey: str), refs #440"), which introduced the strategy and both branches in one commit. The recursion has never forwarded the arguments, so this looks like an oversight in the original commit rather than a decision.

The existing test hardcoded format=Format.CSV (tests/test_rows_from_file.py:44), which is why it was never caught.

Proposed fix

Forward ignore_extras= and extras_key= to the inner call in both branches, and drop the now-redundant outer _extra_key_strategy wrapper so the strategy is applied once, on the shared CSV path that already implements it.

Note on scope

I would fix the auto-detect branch in the same commit, since it is the same root cause (same dropped-argument recursion, same dead wrapper) and would otherwise be a one-line follow-up. It interacts with #891: once the sniffer picks the right delimiter for a ragged file, the auto-detected path will honour ignore_extras too.

I did not add an auto-detect regression test, because csv.Sniffer returns the wrong delimiter on a small ragged input and pinning today's sniffing behaviour would bake in the bug #891 is about. The TSV test passes an explicit format, so it does not depend on the sniffer.

主要言語
Python
スター
2.2k
フォーク
215
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

simonw/sqlite-utils のほかの issue

simonw/sqlite-utils の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。