Skip to content

Commit

Permalink
整理: UTF8設定時の sys.std* is None を切り出し (#1316)
Browse files Browse the repository at this point in the history
* refactor: `sys.std* is None` を切り出し

* Apply suggestions from code review

---------

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>
  • Loading branch information
tarepan and Hiroshiba committed May 29, 2024
1 parent 718c89e commit fcb964c
Showing 1 changed file with 21 additions and 17 deletions.
38 changes: 21 additions & 17 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,34 +51,38 @@ def set_output_log_utf8() -> None:
"""標準出力と標準エラー出力の出力形式を UTF-8 ベースに切り替える"""

# NOTE: for 文で回せないため関数内関数で実装している
def _prepare_utf8_stdio(stdio: TextIO | None) -> TextIO | None:
def _prepare_utf8_stdio(stdio: TextIO) -> TextIO:
"""UTF-8 ベースの標準入出力インターフェイスを用意する"""

CODEC = "utf-8" # locale に依存せず UTF-8 コーデックを用いる
ERR = "backslashreplace" # 不正な形式のデータをバックスラッシュ付きのエスケープシーケンスに置換する

# Python インタープリタが標準入出力へ接続されていないため設定不要とみなしそのまま返す
if stdio is None:
# 既定の `TextIOWrapper` 入出力インターフェイスを UTF-8 へ再設定して返す
if isinstance(stdio, TextIOWrapper):
stdio.reconfigure(encoding=CODEC)
return stdio
else:
# 既定の `TextIOWrapper` 入出力インターフェイスを UTF-8 へ再設定して返す
if isinstance(stdio, TextIOWrapper):
stdio.reconfigure(encoding=CODEC)
# 既定インターフェイスのバッファを全て出力しきった上で UTF-8 設定の `TextIOWrapper` を生成して返す
stdio.flush()
try:
return TextIOWrapper(stdio.buffer, encoding=CODEC, errors=ERR)
except AttributeError:
# バッファへのアクセスに失敗した場合、設定変更をおこなわず返す
return stdio
else:
# 既定インターフェイスのバッファを全て出力しきった上で UTF-8 設定の `TextIOWrapper` を生成して返す
stdio.flush()
try:
return TextIOWrapper(stdio.buffer, encoding=CODEC, errors=ERR)
except AttributeError:
# バッファへのアクセスに失敗した場合、設定変更をおこなわず返す
return stdio

# NOTE:
# `sys.std*` はコンソールがない環境だと `None` をとる (出典: https://docs.python.org/ja/3/library/sys.html#sys.__stdin__ ) # noqa: B950
# しかし `TextIO | None` でなく `TextIO` と間違って型付けされているため、ここでは ignore している
sys.stdout = _prepare_utf8_stdio(sys.stdout) # type: ignore[assignment]
sys.stderr = _prepare_utf8_stdio(sys.stderr) # type: ignore[assignment]
# これは Python インタープリタが標準入出力へ接続されていないことを意味するため、設定不要とみなす

if sys.stdout is None:
pass
else:
sys.stdout = _prepare_utf8_stdio(sys.stdout)

if sys.stderr is None:
pass
else:
sys.stderr = _prepare_utf8_stdio(sys.stderr)


T = TypeVar("T")
Expand Down

0 comments on commit fcb964c

Please sign in to comment.