3

正確な形式に従う必要がある引数のカスタム正規表現型を定義しました。非常に便利な別の投稿 ( regex custom type ) のコードを使用しました。私の問題は、正規表現が失敗すると予想される単体テストを作成し、argparse.ArgumentErrorが発生したことをアサートしようとしていることです ( assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split())))。問題は、argparse が ArgumentError をキャッチして一般的なエラーをスローしているように見えるため、失敗の原因を検証できないことです。何か不足していますか?

トレースバックは次のとおりです。

Error
Traceback (most recent call last):
  File "/Users/markebbert/PyCharmProjects/newproject/unittests.py", line 203, in test_set_operation_parameter
    self.assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split()))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1688, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1727, in parse_known_args
self.error(str(err))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 2347, in error
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 2335, in exit
    _sys.exit(status)
SystemExit: 2

定義したカスタム タイプとパーサー コードは次のとおりです。

class RegexValidator(object):
    """
    Performs regular expression match on value.
    If match fails an ArgumentError is raised
    """

    def __init__(self, pattern, statement=None):
        self.pattern = re.compile(pattern)
        self.statement = statement
        if not self.statement:
            self.statement = "must match pattern %s" % self.pattern

    def __call__(self, string):
        match = self.pattern.search(string)
        if not match:
            raise argparse.ArgumentError(None, self.statement)
        return string


operatorRV = RegexValidator(
    "^((\w+)=)?[iIuUcC]\[(\w+(\[\w+(,\w+)*\])?)(:\w+(\[\w+(,\w+)*\])?)*\]$",
    "Set operations must conform to...")

parser = argparse.ArgumentParser(
    description='Compare variants across individuals',
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

group.add_argument('-s', '--set-operation', dest='operation', nargs='+',
                   type=operatorRV,
                   help="blah.")

単体テストは次のとおりです。

    # Fail for ending colon
    inargs = "-s out=i[one[id1]:]"
    self.assertRaises(argparse.ArgumentError, parser.parse_args(inargs.split()))
4

1 に答える 1

3

Argparse はコマンド ライン パーサーであり、エラーは常に を呼び出し、エラー コードでargparse.exit()呼び出します。sys.exit()これは仕様によるものです。

単体テストの場合、パーサー.error()のメソッドまたはメソッドにモンキーパッチを適用する必要があります (おそらくモッキングを使用) 。エラーメッセージで呼び出され、使用法メッセージを出力してから、終了コードとエラーメッセージで呼び出します。.exit().error().exit()

現在の実装:

# ===============
# Exiting methods
# ===============
def exit(self, status=0, message=None):
    if message:
        self._print_message(message, _sys.stderr)
    _sys.exit(status)

def error(self, message):
    """error(message: string)

    Prints a usage message incorporating the message to stderr and
    exits.

    If you override this in a subclass, it should not return -- it
    should either exit or raise an exception.
    """
    self.print_usage(_sys.stderr)
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
于 2013-03-28T21:13:05.670 に答える