python / python/typeshed

Implications of Union in argparse.Action.__call__ parameter types

オープン
#7,559 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Python
スター
5.1k
フォーク
2.1k
平均マージ
1日 19時間
マージ済み PR(30日)
82

説明

https://github.com/python/typeshed/blob/c41034c3540c5abda10008dd6c17d8e6ff6cc634/stdlib/argparse.pyi#L364-L366
I'm wondering if the reasoning behind this choice has been discussed before. Return types of library functions generally avoid Union (python/mypy#1693). To me, the parameters of a user-provided callback are similar to the return type of a library function—the annotations reflect objects passed to user code, and the user may have runtime control of their types. It is, however, more removed from the runtime context because the class must be first defined and then referenced.

If I override __call__ with an implementation that will only ever see str:

import argparse

class CSVCallback(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, list(values.split(',')))

parser = argparse.ArgumentParser()
parser.add_argument('-o', action=CSVCallback, default=[])

args = parser.parse_args()

pyright complains, based on what appears to be a correct interpretation of the stub:

  repr.py:5:51 - error: Cannot access member "split" for type "Sequence[Any]"
    Member "split" is unknown (reportGeneralTypeIssues)
  repr.py:5:51 - error: "split" is not a known member of "None" (reportOptionalMemberAccess)

Would the appropriate solution be to add assert isinstance(values, str) at the beginning of every callback? Or is this actually abuse of action=..., which should be replaced with type=..., like this?

def csv_callback(value: str) -> list[str]:
    return list(value.split(','))

parser.add_argument('-o', type=csv_callback, default=[])

Since these examples are based on 10-year-old optparse code that was ported 1:1 to argparse 2 years ago, I'm not considering reimplementing them like that—they aren't broken, and the less trivial examples reference parser.error and the previous value of self.dest. But I'd rather avoid the asserts, so for new code I would probably prefer that pattern.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

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

調査の方向性

まず stdlib/argparse.pyi の364-366行目と、ライブラリインターフェースにおける Union についてのリンク先の議論を確認してください。Action callback の例と type= の例を比較し、stub を変更すべきか、既存の annotation をドキュメント化すべきかを判断してください。完了には maintainer が承認した解決が必要です。

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

評価

技術スタック
python
領域
tooling
issue の種類
バグ
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
25/100

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

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