_stream_info / _uri_utils / _exceptions

「線索卡」資料結構、URI 解析、例外層
檔案:_stream_info.py · _uri_utils.py · _exceptions.py

大方向

這三個檔案是核心的「周邊積木」:StreamInfo 是整個調度系統流通的資料結構 (graphify 掃描顯示它是全圖連線數最多的 god node,154 條邊);_uri_utils 負責 file:/data: URI 的解析;_exceptions 定義例外層。


1. StreamInfo(_stream_info.py)

StreamInfo(dataclass, kw_only, frozen) 核心描述檔案「看起來是什麼」的線索卡。

六個欄位都可為 None:mimetype / extension / charset / filename / local_path / urlfrozen=True(不可變)+ kw_only=True——安全且防錯位。 來源:本機路徑、URL、HTTP header(Content-Type/Content-Disposition)、或呼叫端手動提供。

StreamInfo.copy_and_update(*args, **kwargs) 工具複製並合併其他 StreamInfo / kwargs,回傳新實例。

因為 frozen,要「在既有線索上補強」就得複製。邏輯:asdict 當基底, 對傳入的 StreamInfo 只蓋非 None 欄位、對 kwargs 全部蓋上。這是 _convert 各入口 疊加猜測的核心工具。

2. URI 解析(_uri_utils.py)

file_uri_to_path(file_uri) -> (netloc, path) 工具把 file:// URI 拆成 netloc 與本機 path。

urllib.request.url2pathname 解出 path;netloc 非空且非 localhost 時 convert_uri 會拒絕(防 file://evil-host/... 這種繞路)。

parse_data_uri(uri) -> (mimetype, attributes, data) 工具把 data: URI 解成 mimetype、屬性與 bytes。

處理 data:<mimetype>;charset=...;base64,<payload> 格式, 解 base64 後回傳,供 convert_uri 丟給 convert_stream

3. 例外層(_exceptions.py)

MarkItDownException(base) 例外所有自訂例外的共同父類。

讓呼叫端可以「一個 except 抓全部 MarkItDown 錯誤」。

MissingDependencyException / UnsupportedFormatException 例外缺依賴 / 無任何 converter 接受。

MissingDependencyException 是「優雅降級」的訊號——audio 等 converter 捕獲它 就跳過該功能繼續輸出 metadata;UnsupportedFormatException 表示型別完全沒人認得。

FailedConversionAttempt / FileConversionException 例外單次嘗試失敗的紀錄;聚合全部失敗的容器。

FailedConversionAttempt 夾帶 converterexc_info (例外型別+值+traceback);FileConversionException.__init__ 收 attempts 清單, str() 時把每個 converter 的失敗原因列出來——這是 _convert 全軍覆沒時 能看到「每個人為什麼失敗」的關鍵。