def test_pattern_fix_identities_2():
    pattern = Required(NotRequired(Argument("X"), Argument("N")),
                       Argument("N"))
    assert pattern.children[0].children[1] == pattern.children[1]
    assert pattern.children[0].children[1] is not pattern.children[1]
    pattern.fix_identities()
    assert pattern.children[0].children[1] is pattern.children[1]
def test_optional_match():
    assert NotRequired(Option("-a")).match([Option("-a")]) == (True, [],
                                                               [Option("-a")])
    assert NotRequired(Option("-a")).match([]) == (True, [], [])
    assert NotRequired(Option("-a")).match([Option("-x")
                                            ]) == (True, [Option("-x")], [])
    assert NotRequired(Option("-a"), Option("-b")).match([Option("-a")]) == (
        True,
        [],
        [Option("-a")],
    )
    assert NotRequired(Option("-a"), Option("-b")).match([Option("-b")]) == (
        True,
        [],
        [Option("-b")],
    )
    assert NotRequired(Option("-a"), Option("-b")).match([Option("-x")]) == (
        True,
        [Option("-x")],
        [],
    )
    assert NotRequired(Argument("N")).match([Argument(None, 9)]) == (
        True,
        [],
        [Argument("N", 9)],
    )
    assert NotRequired(Option("-a"), Option("-b")).match(
        [Option("-b"), Option("-x"),
         Option("-a")]) == (True, [Option("-x")], [Option("-a"),
                                                   Option("-b")])
def test_pattern_fix_repeating_arguments():
    assert Required(Option("-a")).fix_repeating_arguments() == Required(
        Option("-a"))
    assert Required(Argument("N", None)).fix_repeating_arguments() == Required(
        Argument("N", None))
    assert Required(Argument("N"),
                    Argument("N")).fix_repeating_arguments() == Required(
                        Argument("N", []), Argument("N", []))
    assert Either(Argument("N"), OneOrMore(Argument("N"))).fix() == Either(
        Argument("N", []), OneOrMore(Argument("N", [])))
def test_pattern_flat():
    assert Required(OneOrMore(Argument("N")), Option("-a"),
                    Argument("M")).flat() == [
                        Argument("N"),
                        Option("-a"),
                        Argument("M"),
                    ]
    assert Required(NotRequired(OptionsShortcut()),
                    NotRequired(Option("-a", None))).flat(OptionsShortcut) == [
                        OptionsShortcut()
                    ]
def test_command_match():
    assert Command("c").match([Argument(None, "c")]) == (True, [],
                                                         [Command("c", True)])
    assert Command("c").match([Option("-x")]) == (False, [Option("-x")], [])
    assert Command("c").match(
        [Option("-x"), Option("-a"),
         Argument(None, "c")]) == (
             True,
             [Option("-x"), Option("-a")],
             [Command("c", True)],
         )
    assert Either(Command("add", False),
                  Command("rm", False)).match([Argument(None, "rm")]) == (
                      True,
                      [],
                      [Command("rm", True)],
                  )
def test_either_match():
    assert Either(Option("-a"), Option("-b")).match([Option("-a")]) == (
        True,
        [],
        [Option("-a")],
    )
    assert Either(Option("-a"),
                  Option("-b")).match([Option("-a"),
                                       Option("-b")]) == (
                                           True,
                                           [Option("-b")],
                                           [Option("-a")],
                                       )
    assert Either(Option("-a"), Option("-b")).match([Option("-x")]) == (
        False,
        [Option("-x")],
        [],
    )
    assert Either(Option("-a"), Option("-b"),
                  Option("-c")).match([Option("-x"),
                                       Option("-b")]) == (
                                           True,
                                           [Option("-x")],
                                           [Option("-b")],
                                       )
    assert Either(Argument("M"), Required(Argument("N"), Argument("M"))).match(
        [Argument(None, 1), Argument(None, 2)]) == (
            True,
            [],
            [Argument("N", 1), Argument("M", 2)],
        )
def test_option_match():
    assert Option("-a").match([Option("-a", value=True)]) == (
        True,
        [],
        [Option("-a", value=True)],
    )
    assert Option("-a").match([Option("-x")]) == (False, [Option("-x")], [])
    assert Option("-a").match([Argument("N")]) == (False, [Argument("N")], [])
    assert Option("-a").match([Option("-x"),
                               Option("-a"),
                               Argument("N")]) == (
                                   True,
                                   [Option("-x"), Argument("N")],
                                   [Option("-a")],
                               )
    assert Option("-a").match([Option("-a", value=True),
                               Option("-a")]) == (
                                   True,
                                   [Option("-a")],
                                   [Option("-a", value=True)],
                               )
def test_parse_argv():
    o = [Option("-h"), Option("-v", "--verbose"), Option("-f", "--file", 1)]
    TS = lambda s: Tokens(s, error=DocoptExit)
    assert parse_argv(TS(""), options=o) == []
    assert parse_argv(TS("-h"), options=o) == [Option("-h", None, 0, True)]
    assert parse_argv(TS("-h --verbose"), options=o) == [
        Option("-h", None, 0, True),
        Option("-v", "--verbose", 0, True),
    ]
    assert parse_argv(TS("-h --file f.txt"), options=o) == [
        Option("-h", None, 0, True),
        Option("-f", "--file", 1, "f.txt"),
    ]
    assert parse_argv(TS("-h --file f.txt arg"), options=o) == [
        Option("-h", None, 0, True),
        Option("-f", "--file", 1, "f.txt"),
        Argument(None, "arg"),
    ]
    assert parse_argv(TS("-h --file f.txt arg arg2"), options=o) == [
        Option("-h", None, 0, True),
        Option("-f", "--file", 1, "f.txt"),
        Argument(None, "arg"),
        Argument(None, "arg2"),
    ]
    assert parse_argv(TS("-h arg -- -v"), options=o) == [
        Option("-h", None, 0, True),
        Argument(None, "arg"),
        Argument(None, "--"),
        Argument(None, "-v"),
    ]
def test_pattern_either():
    assert transform(Option("-a")) == Either(Required(Option("-a")))
    assert transform(Argument("A")) == Either(Required(Argument("A")))
    assert transform(Required(Either(Option("-a"), Option("-b")),
                              Option("-c"))) == Either(
                                  Required(Option("-a"), Option("-c")),
                                  Required(Option("-b"), Option("-c")))
    assert transform(
        NotRequired(Option("-a"),
                    Either(Option("-b"), Option("-c")))) == Either(
                        Required(Option("-b"), Option("-a")),
                        Required(Option("-c"), Option("-a")))
    assert transform(Either(Option("-x"), Either(Option("-y"),
                                                 Option("-z")))) == Either(
                                                     Required(Option("-x")),
                                                     Required(Option("-y")),
                                                     Required(Option("-z")))
    assert transform(OneOrMore(Argument("N"), Argument("M"))) == Either(
        Required(Argument("N"), Argument("M"), Argument("N"), Argument("M")))
def test_set():
    assert Argument("N") == Argument("N")
    assert set([Argument("N"), Argument("N")]) == set([Argument("N")])
def test_basic_pattern_matching():
    # ( -a N [ -x Z ] )
    pattern = Required(Option("-a"), Argument("N"),
                       NotRequired(Option("-x"), Argument("Z")))
    # -a N
    assert pattern.match([Option("-a"), Argument(None, 9)]) == (
        True,
        [],
        [Option("-a"), Argument("N", 9)],
    )
    # -a -x N Z
    assert pattern.match(
        [Option("-a"),
         Option("-x"),
         Argument(None, 9),
         Argument(None, 5)]) == (
             True,
             [],
             [Option("-a"),
              Argument("N", 9),
              Option("-x"),
              Argument("Z", 5)],
         )
    # -x N Z  # BZZ!
    assert pattern.match(
        [Option("-x"), Argument(None, 9),
         Argument(None, 5)]) == (
             False,
             [Option("-x"), Argument(None, 9),
              Argument(None, 5)],
             [],
         )
def test_list_argument_match():
    assert Required(Argument("N"), Argument("N")).fix().match(
        [Argument(None, "1"),
         Argument(None, "2")]) == (True, [], [Argument("N", ["1", "2"])])
    assert OneOrMore(Argument("N")).fix().match(
        [Argument(None, "1"),
         Argument(None, "2"),
         Argument(None, "3")]) == (True, [], [Argument("N", ["1", "2", "3"])])
    assert Required(Argument("N"), OneOrMore(Argument("N"))).fix().match(
        [Argument(None, "1"),
         Argument(None, "2"),
         Argument(None, "3")]) == (
             True,
             [],
             [Argument("N", ["1", "2", "3"])],
         )
    assert Required(Argument("N"), Required(Argument("N"))).fix().match(
        [Argument(None, "1"),
         Argument(None, "2")]) == (True, [], [Argument("N", ["1", "2"])])
def test_one_or_more_match():
    assert OneOrMore(Argument("N")).match([Argument(None, 9)]) == (
        True,
        [],
        [Argument("N", 9)],
    )
    assert OneOrMore(Argument("N")).match([]) == (False, [], [])
    assert OneOrMore(Argument("N")).match([Option("-x")
                                           ]) == (False, [Option("-x")], [])
    assert OneOrMore(Argument("N")).match(
        [Argument(None, 9), Argument(None, 8)]) == (
            True,
            [],
            [Argument("N", 9), Argument("N", 8)],
        )
    assert OneOrMore(Argument("N")).match(
        [Argument(None, 9), Option("-x"),
         Argument(None, 8)]) == (
             True,
             [Option("-x")],
             [Argument("N", 9), Argument("N", 8)],
         )
    assert OneOrMore(Option("-a")).match(
        [Option("-a"), Argument(None, 8),
         Option("-a")]) == (
             True,
             [Argument(None, 8)],
             [Option("-a"), Option("-a")],
         )
    assert OneOrMore(Option("-a")).match([Argument(
        None, 8), Option("-x")]) == (
            False,
            [Argument(None, 8), Option("-x")],
            [],
        )
    assert OneOrMore(Required(Option("-a"), Argument("N"))).match([
        Option("-a"),
        Argument(None, 1),
        Option("-x"),
        Option("-a"),
        Argument(None, 2)
    ]) == (
        True,
        [Option("-x")],
        [Option("-a"),
         Argument("N", 1),
         Option("-a"),
         Argument("N", 2)],
    )
    assert OneOrMore(NotRequired(Argument("N"))).match([Argument(None, 9)
                                                        ]) == (
                                                            True,
                                                            [],
                                                            [Argument("N", 9)],
                                                        )
def test_argument_match():
    assert Argument("N").match([Argument(None,
                                         9)]) == (True, [], [Argument("N", 9)])
    assert Argument("N").match([Option("-x")]) == (False, [Option("-x")], [])
    assert Argument("N").match([Option("-x"),
                                Option("-a"),
                                Argument(None, 5)]) == (
                                    True,
                                    [Option("-x"), Option("-a")],
                                    [Argument("N", 5)],
                                )
    assert Argument("N").match([Argument(None, 9),
                                Argument(None, 0)]) == (
                                    True,
                                    [Argument(None, 0)],
                                    [Argument("N", 9)],
                                )
def test_parse_pattern():
    o = [Option("-h"), Option("-v", "--verbose"), Option("-f", "--file", 1)]
    assert parse_pattern("[ -h ]",
                         options=o) == Required(NotRequired(Option("-h")))
    assert parse_pattern("[ ARG ... ]", options=o) == Required(
        NotRequired(OneOrMore(Argument("ARG"))))
    assert parse_pattern("[ -h | -v ]", options=o) == Required(
        NotRequired(Either(Option("-h"), Option("-v", "--verbose"))))
    assert parse_pattern("( -h | -v [ --file <f> ] )", options=o) == Required(
        Required(
            Either(
                Option("-h"),
                Required(
                    Option("-v", "--verbose"),
                    NotRequired(Option("-f", "--file", 1, None)),
                ),
            )))
    assert parse_pattern("(-h|-v[--file=<f>]N...)", options=o) == Required(
        Required(
            Either(
                Option("-h"),
                Required(
                    Option("-v", "--verbose"),
                    NotRequired(Option("-f", "--file", 1, None)),
                    OneOrMore(Argument("N")),
                ),
            )))
    assert parse_pattern("(N [M | (K | L)] | O P)", options=[]) == Required(
        Required(
            Either(
                Required(
                    Argument("N"),
                    NotRequired(
                        Either(
                            Argument("M"),
                            Required(Either(Argument("K"), Argument("L"))),
                        )),
                ),
                Required(Argument("O"), Argument("P")),
            )))
    assert parse_pattern("[ -h ] [N]",
                         options=o) == Required(NotRequired(Option("-h")),
                                                NotRequired(Argument("N")))
    assert parse_pattern("[options]",
                         options=o) == Required(NotRequired(OptionsShortcut()))
    assert parse_pattern("[options] A",
                         options=o) == Required(NotRequired(OptionsShortcut()),
                                                Argument("A"))
    assert parse_pattern("-v [options]",
                         options=o) == Required(Option("-v", "--verbose"),
                                                NotRequired(OptionsShortcut()))
    assert parse_pattern("ADD", options=o) == Required(Argument("ADD"))
    assert parse_pattern("<add>", options=o) == Required(Argument("<add>"))
    assert parse_pattern("add", options=o) == Required(Command("add"))