Show More
@@ -2,17 +2,25 b'' | |||
|
2 | 2 | |
|
3 | 3 | # Copyright © 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>. |
|
4 | 4 | # |
|
5 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
|
6 | # use this file except in compliance with the License. You may obtain a copy | |
|
7 | # of the License at | |
|
5 | # Redistribution and use in source and binary forms, with or without | |
|
6 | # modification, are permitted provided that the following conditions are met: | |
|
8 | 7 | # |
|
9 | # http://www.apache.org/licenses/LICENSE-2.0 | |
|
8 | # * Redistributions of source code must retain the above copyright notice, this | |
|
9 | # list of conditions and the following disclaimer. | |
|
10 | # * Redistributions in binary form must reproduce the above copyright notice, | |
|
11 | # this list of conditions and the following disclaimer in the documentation | |
|
12 | # and/or other materials provided with the distribution. | |
|
10 | 13 | # |
|
11 | # Unless required by applicable law or agreed to in writing, software | |
|
12 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
|
13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
|
14 | # License for the specific language governing permissions and limitations | |
|
15 | # under the License. | |
|
14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
|
15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
|
16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
|
17 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
|
18 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
|
19 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
|
20 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|
21 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
|
22 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
|
23 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
|
16 | 24 | |
|
17 | 25 | """Command-line parsing library |
|
18 | 26 | |
@@ -75,7 +83,7 b' considered public as object names -- the API of the formatter objects is' | |||
|
75 | 83 | still considered an implementation detail.) |
|
76 | 84 | """ |
|
77 | 85 | |
|
78 | __version__ = '1.0' | |
|
86 | __version__ = '1.0.1' | |
|
79 | 87 | __all__ = [ |
|
80 | 88 | 'ArgumentParser', |
|
81 | 89 | 'ArgumentError', |
@@ -118,6 +126,15 b' except NameError:' | |||
|
118 | 126 | result.reverse() |
|
119 | 127 | return result |
|
120 | 128 | |
|
129 | # silence Python 2.6 buggy warnings about Exception.message | |
|
130 | if _sys.version_info[:2] == (2, 6): | |
|
131 | import warnings | |
|
132 | warnings.filterwarnings( | |
|
133 | action='ignore', | |
|
134 | message='BaseException.message has been deprecated as of Python 2.6', | |
|
135 | category=DeprecationWarning, | |
|
136 | module='argparse') | |
|
137 | ||
|
121 | 138 | |
|
122 | 139 | SUPPRESS = '==SUPPRESS==' |
|
123 | 140 | |
@@ -297,7 +314,7 b' class HelpFormatter(object):' | |||
|
297 | 314 | # Help-formatting methods |
|
298 | 315 | # ======================= |
|
299 | 316 | def format_help(self): |
|
300 |
help = self._root_section.format_help() |
|
|
317 | help = self._root_section.format_help() | |
|
301 | 318 | if help: |
|
302 | 319 | help = self._long_break_matcher.sub('\n\n', help) |
|
303 | 320 | help = help.strip('\n') + '\n' |
@@ -312,13 +329,17 b' class HelpFormatter(object):' | |||
|
312 | 329 | if prefix is None: |
|
313 | 330 | prefix = _('usage: ') |
|
314 | 331 | |
|
332 | # if usage is specified, use that | |
|
333 | if usage is not None: | |
|
334 | usage = usage % dict(prog=self._prog) | |
|
335 | ||
|
315 | 336 | # if no optionals or positionals are available, usage is just prog |
|
316 | if usage is None and not actions: | |
|
317 | usage = '%(prog)s' | |
|
337 | elif usage is None and not actions: | |
|
338 | usage = '%(prog)s' % dict(prog=self._prog) | |
|
318 | 339 | |
|
319 | 340 | # if optionals and positionals are available, calculate usage |
|
320 | 341 | elif usage is None: |
|
321 |
|
|
|
342 | prog = '%(prog)s' % dict(prog=self._prog) | |
|
322 | 343 | |
|
323 | 344 | # split optionals from positionals |
|
324 | 345 | optionals = [] |
@@ -329,44 +350,69 b' class HelpFormatter(object):' | |||
|
329 | 350 | else: |
|
330 | 351 | positionals.append(action) |
|
331 | 352 | |
|
332 | # determine width of "usage: PROG" and width of text | |
|
333 | prefix_width = len(prefix) + len(usage) + 1 | |
|
334 | prefix_indent = self._current_indent + prefix_width | |
|
335 | text_width = self._width - self._current_indent | |
|
336 | ||
|
337 | # put them on one line if they're short enough | |
|
353 | # build full usage string | |
|
338 | 354 | format = self._format_actions_usage |
|
339 | 355 | action_usage = format(optionals + positionals, groups) |
|
340 | if prefix_width + len(action_usage) + 1 < text_width: | |
|
341 | usage = '%s %s' % (usage, action_usage) | |
|
356 | usage = ' '.join([s for s in [prog, action_usage] if s]) | |
|
357 | ||
|
358 | # wrap the usage parts if it's too long | |
|
359 | text_width = self._width - self._current_indent | |
|
360 | if len(prefix) + len(usage) > text_width: | |
|
361 | ||
|
362 | # break usage into wrappable parts | |
|
363 | part_regexp = r'\(.*?\)+|\[.*?\]+|\S+' | |
|
364 | opt_usage = format(optionals, groups) | |
|
365 | pos_usage = format(positionals, groups) | |
|
366 | opt_parts = _re.findall(part_regexp, opt_usage) | |
|
367 | pos_parts = _re.findall(part_regexp, pos_usage) | |
|
368 | assert ' '.join(opt_parts) == opt_usage | |
|
369 | assert ' '.join(pos_parts) == pos_usage | |
|
370 | ||
|
371 | # helper for wrapping lines | |
|
372 | def get_lines(parts, indent, prefix=None): | |
|
373 | lines = [] | |
|
374 | line = [] | |
|
375 | if prefix is not None: | |
|
376 | line_len = len(prefix) - 1 | |
|
377 | else: | |
|
378 | line_len = len(indent) - 1 | |
|
379 | for part in parts: | |
|
380 | if line_len + 1 + len(part) > text_width: | |
|
381 | lines.append(indent + ' '.join(line)) | |
|
382 | line = [] | |
|
383 | line_len = len(indent) - 1 | |
|
384 | line.append(part) | |
|
385 | line_len += len(part) + 1 | |
|
386 | if line: | |
|
387 | lines.append(indent + ' '.join(line)) | |
|
388 | if prefix is not None: | |
|
389 | lines[0] = lines[0][len(indent):] | |
|
390 | return lines | |
|
391 | ||
|
392 | # if prog is short, follow it with optionals or positionals | |
|
393 | if len(prefix) + len(prog) <= 0.75 * text_width: | |
|
394 | indent = ' ' * (len(prefix) + len(prog) + 1) | |
|
395 | if opt_parts: | |
|
396 | lines = get_lines([prog] + opt_parts, indent, prefix) | |
|
397 | lines.extend(get_lines(pos_parts, indent)) | |
|
398 | elif pos_parts: | |
|
399 | lines = get_lines([prog] + pos_parts, indent, prefix) | |
|
400 | else: | |
|
401 | lines = [prog] | |
|
342 | 402 | |
|
343 | # if they're long, wrap optionals and positionals individually | |
|
403 | # if prog is long, put it on its own line | |
|
344 | 404 | else: |
|
345 | optional_usage = format(optionals, groups) | |
|
346 | positional_usage = format(positionals, groups) | |
|
347 | indent = ' ' * prefix_indent | |
|
348 | ||
|
349 | # usage is made of PROG, optionals and positionals | |
|
350 | parts = [usage, ' '] | |
|
351 | ||
|
352 | # options always get added right after PROG | |
|
353 | if optional_usage: | |
|
354 | parts.append(_textwrap.fill( | |
|
355 | optional_usage, text_width, | |
|
356 | initial_indent=indent, | |
|
357 | subsequent_indent=indent).lstrip()) | |
|
358 | ||
|
359 | # if there were options, put arguments on the next line | |
|
360 | # otherwise, start them right after PROG | |
|
361 | if positional_usage: | |
|
362 | part = _textwrap.fill( | |
|
363 | positional_usage, text_width, | |
|
364 | initial_indent=indent, | |
|
365 | subsequent_indent=indent).lstrip() | |
|
366 | if optional_usage: | |
|
367 | part = '\n' + indent + part | |
|
368 | parts.append(part) | |
|
369 | usage = ''.join(parts) | |
|
405 | indent = ' ' * len(prefix) | |
|
406 | parts = opt_parts + pos_parts | |
|
407 | lines = get_lines(parts, indent) | |
|
408 | if len(lines) > 1: | |
|
409 | lines = [] | |
|
410 | lines.extend(get_lines(opt_parts, indent)) | |
|
411 | lines.extend(get_lines(pos_parts, indent)) | |
|
412 | lines = [prog] + lines | |
|
413 | ||
|
414 | # join lines into usage | |
|
415 | usage = '\n'.join(lines) | |
|
370 | 416 | |
|
371 | 417 | # prefix with 'usage:' |
|
372 | 418 | return '%s%s\n\n' % (prefix, usage) |
@@ -787,7 +833,9 b' class _StoreAction(Action):' | |||
|
787 | 833 | help=None, |
|
788 | 834 | metavar=None): |
|
789 | 835 | if nargs == 0: |
|
790 |
raise ValueError('nargs must be > 0' |
|
|
836 | raise ValueError('nargs for store actions must be > 0; if you ' | |
|
837 | 'have nothing to store, actions such as store ' | |
|
838 | 'true or store const may be more appropriate') | |
|
791 | 839 | if const is not None and nargs != OPTIONAL: |
|
792 | 840 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) |
|
793 | 841 | super(_StoreAction, self).__init__( |
@@ -877,7 +925,9 b' class _AppendAction(Action):' | |||
|
877 | 925 | help=None, |
|
878 | 926 | metavar=None): |
|
879 | 927 | if nargs == 0: |
|
880 |
raise ValueError('nargs must be > 0' |
|
|
928 | raise ValueError('nargs for append actions must be > 0; if arg ' | |
|
929 | 'strings are not supplying the value to append, ' | |
|
930 | 'the append const action may be more appropriate') | |
|
881 | 931 | if const is not None and nargs != OPTIONAL: |
|
882 | 932 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) |
|
883 | 933 | super(_AppendAction, self).__init__( |
@@ -1281,6 +1331,17 b' class _ActionsContainer(object):' | |||
|
1281 | 1331 | for action in group._group_actions: |
|
1282 | 1332 | group_map[action] = title_group_map[group.title] |
|
1283 | 1333 | |
|
1334 | # add container's mutually exclusive groups | |
|
1335 | # NOTE: if add_mutually_exclusive_group ever gains title= and | |
|
1336 | # description= then this code will need to be expanded as above | |
|
1337 | for group in container._mutually_exclusive_groups: | |
|
1338 | mutex_group = self.add_mutually_exclusive_group( | |
|
1339 | required=group.required) | |
|
1340 | ||
|
1341 | # map the actions to their new mutex group | |
|
1342 | for action in group._group_actions: | |
|
1343 | group_map[action] = mutex_group | |
|
1344 | ||
|
1284 | 1345 | # add all actions to this container or their group |
|
1285 | 1346 | for action in container._actions: |
|
1286 | 1347 | group_map.get(action, self)._add_action(action) |
@@ -2114,6 +2175,7 b' class ArgumentParser(_AttributeHolder, _ActionsContainer):' | |||
|
2114 | 2175 | def _get_value(self, action, arg_string): |
|
2115 | 2176 | type_func = self._registry_get('type', action.type, action.type) |
|
2116 | 2177 | if not hasattr(type_func, '__call__'): |
|
2178 | if not hasattr(type_func, '__bases__'): # classic classes | |
|
2117 | 2179 | msg = _('%r is not callable') |
|
2118 | 2180 | raise ArgumentError(action, msg % type_func) |
|
2119 | 2181 |
General Comments 0
You need to be logged in to leave comments.
Login now