1# Copyright (C) 2017, Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import argparse
16import textwrap
17
18from cliff import sphinxext
19from cliff.tests import base
20
21
22class TestSphinxExtension(base.TestBase):
23
24    def test_empty_help(self):
25        """Handle positional and optional actions without help messages."""
26        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
27        parser.add_argument('name', action='store')
28        parser.add_argument('--language', dest='lang')
29
30        output = '\n'.join(sphinxext._format_parser(parser))
31        self.assertEqual(textwrap.dedent("""
32        .. program:: hello-world
33        .. code-block:: shell
34
35            hello-world [--language LANG] name
36
37        .. option:: --language <LANG>
38
39        .. option:: name
40        """).lstrip(), output)
41
42    def test_nonempty_help(self):
43        """Handle positional and optional actions with help messages."""
44        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
45        parser.add_argument('name', help='user name')
46        parser.add_argument('--language', dest='lang',
47                            help='greeting language')
48
49        output = '\n'.join(sphinxext._format_parser(parser))
50        self.assertEqual(textwrap.dedent("""
51        .. program:: hello-world
52        .. code-block:: shell
53
54            hello-world [--language LANG] name
55
56        .. option:: --language <LANG>
57
58            greeting language
59
60        .. option:: name
61
62            user name
63        """).lstrip(), output)
64
65    def test_description_epilog(self):
66        """Handle a parser description, epilog."""
67        parser = argparse.ArgumentParser(prog='hello-world', add_help=False,
68                                         description='A "Hello, World" app.',
69                                         epilog='What am I doing down here?')
70        parser.add_argument('name', action='store')
71        parser.add_argument('--language', dest='lang')
72
73        output = '\n'.join(sphinxext._format_parser(parser))
74        self.assertEqual(textwrap.dedent("""
75        A "Hello, World" app.
76
77        .. program:: hello-world
78        .. code-block:: shell
79
80            hello-world [--language LANG] name
81
82        .. option:: --language <LANG>
83
84        .. option:: name
85
86        What am I doing down here?
87        """).lstrip(), output)
88
89    def test_flag(self):
90        """Handle a boolean argparse action."""
91        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
92        parser.add_argument('name', help='user name')
93        parser.add_argument('--translate', action='store_true',
94                            help='translate to local language')
95
96        output = '\n'.join(sphinxext._format_parser(parser))
97        self.assertEqual(textwrap.dedent("""
98        .. program:: hello-world
99        .. code-block:: shell
100
101            hello-world [--translate] name
102
103        .. option:: --translate
104
105            translate to local language
106
107        .. option:: name
108
109            user name
110        """).lstrip(), output)
111
112    def test_supressed(self):
113        """Handle a supressed action."""
114        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
115        parser.add_argument('name', help='user name')
116        parser.add_argument('--variable', help=argparse.SUPPRESS)
117
118        output = '\n'.join(sphinxext._format_parser(parser))
119        self.assertEqual(textwrap.dedent("""
120        .. program:: hello-world
121        .. code-block:: shell
122
123            hello-world name
124
125
126        .. option:: name
127
128            user name
129        """).lstrip(), output)
130
131    def test_metavar(self):
132        """Handle an option with a metavar."""
133        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
134        parser.add_argument('names', metavar='<NAME>', nargs='+',
135                            help='a user name')
136
137        output = '\n'.join(sphinxext._format_parser(parser))
138        self.assertEqual(textwrap.dedent("""
139        .. program:: hello-world
140        .. code-block:: shell
141
142            hello-world <NAME> [<NAME> ...]
143
144        .. option:: NAME
145
146            a user name
147        """).lstrip(), output)
148
149    def test_multiple_opts(self):
150        """Correctly output multiple opts on separate lines."""
151        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
152        parser.add_argument('name', help='user name')
153        parser.add_argument('--language', dest='lang',
154                            help='greeting language')
155        parser.add_argument('--translate', action='store_true',
156                            help='translate to local language')
157        parser.add_argument('--write-to-var-log-something-or-other',
158                            action='store_true',
159                            help='a long opt to force wrapping')
160        parser.add_argument('--required-arg', dest='stuff', required=True,
161                            help='a required argument')
162        style_group = parser.add_mutually_exclusive_group(required=True)
163        style_group.add_argument('--polite', action='store_true',
164                                 help='use a polite greeting')
165        style_group.add_argument('--profane', action='store_true',
166                                 help='use a less polite greeting')
167
168        output = '\n'.join(sphinxext._format_parser(parser))
169        self.assertEqual(textwrap.dedent("""
170        .. program:: hello-world
171        .. code-block:: shell
172
173            hello-world
174                [--language LANG]
175                [--translate]
176                [--write-to-var-log-something-or-other]
177                --required-arg STUFF
178                (--polite | --profane)
179                name
180
181        .. option:: --language <LANG>
182
183            greeting language
184
185        .. option:: --translate
186
187            translate to local language
188
189        .. option:: --write-to-var-log-something-or-other
190
191            a long opt to force wrapping
192
193        .. option:: --required-arg <STUFF>
194
195            a required argument
196
197        .. option:: --polite
198
199            use a polite greeting
200
201        .. option:: --profane
202
203            use a less polite greeting
204
205        .. option:: name
206
207            user name
208        """).lstrip(), output)
209
210    def test_various_option_names_with_hyphen(self):
211        """Handle options whose name and/or metavar contain hyphen(s)"""
212        parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
213        parser.add_argument('--foo-bar', metavar='<foo-bar>',
214                            help='foo bar', required=True)
215        parser.add_argument('--foo-bar-baz', metavar='<foo-bar-baz>',
216                            help='foo bar baz', required=True)
217        parser.add_argument('--foo', metavar='<foo>',
218                            help='foo', required=True)
219        parser.add_argument('--alpha', metavar='<A>',
220                            help='alpha')
221        parser.add_argument('--alpha-beta', metavar='<A-B>',
222                            help='alpha beta')
223        parser.add_argument('--alpha-beta-gamma', metavar='<A-B-C>',
224                            help='alpha beta gamma')
225
226        output = '\n'.join(sphinxext._format_parser(parser))
227        self.assertEqual(textwrap.dedent("""
228        .. program:: hello-world
229        .. code-block:: shell
230
231            hello-world
232                --foo-bar <foo-bar>
233                --foo-bar-baz <foo-bar-baz>
234                --foo <foo>
235                [--alpha <A>]
236                [--alpha-beta <A-B>]
237                [--alpha-beta-gamma <A-B-C>]
238
239        .. option:: --foo-bar <foo-bar>
240
241            foo bar
242
243        .. option:: --foo-bar-baz <foo-bar-baz>
244
245            foo bar baz
246
247        .. option:: --foo <foo>
248
249            foo
250
251        .. option:: --alpha <A>
252
253            alpha
254
255        .. option:: --alpha-beta <A-B>
256
257            alpha beta
258
259        .. option:: --alpha-beta-gamma <A-B-C>
260
261            alpha beta gamma
262        """).lstrip(), output)
263