1# coding: utf-8
2"""
3Regression tests
4~~~~~~~~~~~~~~~~
5"""
6import pytest
7import argh
8
9from .base import DebugArghParser, run
10
11
12def test_regression_issue12():
13    """
14    Issue #12: @command was broken if there were more than one argument
15    to begin with same character (i.e. short option names were inferred
16    incorrectly).
17    """
18
19    def cmd(foo=1, fox=2):
20        yield 'foo {0}, fox {1}'.format(foo, fox)
21
22    p = DebugArghParser()
23    p.set_default_command(cmd)
24
25    assert run(p, '').out ==  'foo 1, fox 2\n'
26    assert run(p, '--foo 3').out == 'foo 3, fox 2\n'
27    assert run(p, '--fox 3').out == 'foo 1, fox 3\n'
28    assert 'unrecognized' in run(p, '-f 3', exit=True)
29
30
31def test_regression_issue12_help_flag():
32    """
33    Issue #12: if an argument starts with "h", e.g. "--host",
34    ArgumentError is raised because "--help" is always added by argh
35    without decorators.
36    """
37    def ddos(host='localhost'):
38        return 'so be it, {0}!'.format(host)
39
40    # no help → no conflict
41    p = DebugArghParser('PROG', add_help=False)
42    p.set_default_command(ddos)
43    assert run(p, '-h 127.0.0.1').out == 'so be it, 127.0.0.1!\n'
44
45    # help added → conflict → short name ignored
46    p = DebugArghParser('PROG', add_help=True)
47    p.set_default_command(ddos)
48    assert None == run(p, '-h 127.0.0.1', exit=True)
49
50
51def test_regression_issue27():
52    """
53    Issue #27: store_true is not set for inferred bool argument.
54
55    :Reason: when @command was refactored, it stopped using @arg, but it is
56    it was there that guesses (choices→type, default→type and
57    default→action) were made.
58    """
59    def parrot(dead=False):
60        return 'this parrot is no more' if dead else 'beautiful plumage'
61
62    def grenade(count=3):
63        if count == 3:
64            return 'Three shall be the number thou shalt count'
65        else:
66            return '{0!r} is right out'.format(count)
67
68    p = DebugArghParser()
69    p.add_commands([parrot, grenade])
70
71    # default → type (int)
72    assert run(p, 'grenade').out == ('Three shall be the number '
73                                     'thou shalt count\n')
74    assert run(p, 'grenade --count 5').out == '5 is right out\n'
75
76    # default → action (store_true)
77    assert run(p, 'parrot').out == 'beautiful plumage\n'
78    assert run(p, 'parrot --dead').out == 'this parrot is no more\n'
79
80
81def test_regression_issue31():
82    """
83    Issue #31: Argh fails with parameter action type 'count' if a default
84    value is provided.
85
86    :Reason: assembling._guess() would infer type from default value without
87        regard to the action.  _CountAction does not accept argument "type".
88
89    :Solution: restricted type inferring to actions "store" and "append".
90    """
91
92    @argh.arg('-v', '--verbose', dest='verbose', action='count', default=0)
93    def cmd(**kwargs):
94        yield kwargs.get('verbose', -1)
95
96    p = DebugArghParser()
97    p.set_default_command(cmd)
98    assert '0\n' == run(p, '').out
99    assert '1\n' == run(p, '-v').out
100    assert '2\n' == run(p, '-vv').out
101
102
103def test_regression_issue47():
104    @argh.arg('--foo-bar', default="full")
105    def func(foo_bar):
106        return 'hello'
107
108    p = DebugArghParser()
109    with pytest.raises(argh.assembling.AssemblingError) as excinfo:
110        p.set_default_command(func)
111    msg = ('func: argument "foo_bar" declared as positional (in function '
112           'signature) and optional (via decorator)')
113    assert excinfo.exconly().endswith(msg)
114
115
116def test_regression_issue76():
117    """
118    Issue #76: optional arguments defaulting to the empty string break --help.
119
120    This is also tested in integration tests but in a different way.
121    """
122    def cmd(foo=''):
123        pass
124
125    p = DebugArghParser()
126    p.set_default_command(cmd)
127    run(p, '--help', exit=True)
128