Show More
@@ -2,17 +2,25 b'' | |||||
2 |
|
2 | |||
3 | # Copyright © 2006-2009 Steven J. Bethard <steven.bethard@gmail.com>. |
|
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 |
|
5 | # Redistribution and use in source and binary forms, with or without | |
6 | # use this file except in compliance with the License. You may obtain a copy |
|
6 | # modification, are permitted provided that the following conditions are met: | |
7 | # of the License at |
|
|||
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 |
|
14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
12 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
15 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
16 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
14 | # License for the specific language governing permissions and limitations |
|
17 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
15 | # under the License. |
|
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 | """Command-line parsing library |
|
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 | still considered an implementation detail.) |
|
83 | still considered an implementation detail.) | |
76 | """ |
|
84 | """ | |
77 |
|
85 | |||
78 | __version__ = '1.0' |
|
86 | __version__ = '1.0.1' | |
79 | __all__ = [ |
|
87 | __all__ = [ | |
80 | 'ArgumentParser', |
|
88 | 'ArgumentParser', | |
81 | 'ArgumentError', |
|
89 | 'ArgumentError', | |
@@ -118,6 +126,15 b' except NameError:' | |||||
118 | result.reverse() |
|
126 | result.reverse() | |
119 | return result |
|
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 | SUPPRESS = '==SUPPRESS==' |
|
139 | SUPPRESS = '==SUPPRESS==' | |
123 |
|
140 | |||
@@ -297,7 +314,7 b' class HelpFormatter(object):' | |||||
297 | # Help-formatting methods |
|
314 | # Help-formatting methods | |
298 | # ======================= |
|
315 | # ======================= | |
299 | def format_help(self): |
|
316 | def format_help(self): | |
300 |
help = self._root_section.format_help() |
|
317 | help = self._root_section.format_help() | |
301 | if help: |
|
318 | if help: | |
302 | help = self._long_break_matcher.sub('\n\n', help) |
|
319 | help = self._long_break_matcher.sub('\n\n', help) | |
303 | help = help.strip('\n') + '\n' |
|
320 | help = help.strip('\n') + '\n' | |
@@ -312,13 +329,17 b' class HelpFormatter(object):' | |||||
312 | if prefix is None: |
|
329 | if prefix is None: | |
313 | prefix = _('usage: ') |
|
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 | # if no optionals or positionals are available, usage is just prog |
|
336 | # if no optionals or positionals are available, usage is just prog | |
316 | if usage is None and not actions: |
|
337 | elif usage is None and not actions: | |
317 | usage = '%(prog)s' |
|
338 | usage = '%(prog)s' % dict(prog=self._prog) | |
318 |
|
339 | |||
319 | # if optionals and positionals are available, calculate usage |
|
340 | # if optionals and positionals are available, calculate usage | |
320 | elif usage is None: |
|
341 | elif usage is None: | |
321 |
|
|
342 | prog = '%(prog)s' % dict(prog=self._prog) | |
322 |
|
343 | |||
323 | # split optionals from positionals |
|
344 | # split optionals from positionals | |
324 | optionals = [] |
|
345 | optionals = [] | |
@@ -329,44 +350,69 b' class HelpFormatter(object):' | |||||
329 | else: |
|
350 | else: | |
330 | positionals.append(action) |
|
351 | positionals.append(action) | |
331 |
|
352 | |||
332 | # determine width of "usage: PROG" and width of text |
|
353 | # build full usage string | |
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 |
|
|||
338 | format = self._format_actions_usage |
|
354 | format = self._format_actions_usage | |
339 | action_usage = format(optionals + positionals, groups) |
|
355 | action_usage = format(optionals + positionals, groups) | |
340 | if prefix_width + len(action_usage) + 1 < text_width: |
|
356 | usage = ' '.join([s for s in [prog, action_usage] if s]) | |
341 | usage = '%s %s' % (usage, action_usage) |
|
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 | else: |
|
404 | else: | |
345 | optional_usage = format(optionals, groups) |
|
405 | indent = ' ' * len(prefix) | |
346 | positional_usage = format(positionals, groups) |
|
406 | parts = opt_parts + pos_parts | |
347 | indent = ' ' * prefix_indent |
|
407 | lines = get_lines(parts, indent) | |
348 |
|
408 | if len(lines) > 1: | ||
349 | # usage is made of PROG, optionals and positionals |
|
409 | lines = [] | |
350 | parts = [usage, ' '] |
|
410 | lines.extend(get_lines(opt_parts, indent)) | |
351 |
|
411 | lines.extend(get_lines(pos_parts, indent)) | ||
352 | # options always get added right after PROG |
|
412 | lines = [prog] + lines | |
353 | if optional_usage: |
|
413 | ||
354 | parts.append(_textwrap.fill( |
|
414 | # join lines into usage | |
355 | optional_usage, text_width, |
|
415 | usage = '\n'.join(lines) | |
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) |
|
|||
370 |
|
416 | |||
371 | # prefix with 'usage:' |
|
417 | # prefix with 'usage:' | |
372 | return '%s%s\n\n' % (prefix, usage) |
|
418 | return '%s%s\n\n' % (prefix, usage) | |
@@ -787,7 +833,9 b' class _StoreAction(Action):' | |||||
787 | help=None, |
|
833 | help=None, | |
788 | metavar=None): |
|
834 | metavar=None): | |
789 | if nargs == 0: |
|
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 | if const is not None and nargs != OPTIONAL: |
|
839 | if const is not None and nargs != OPTIONAL: | |
792 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) |
|
840 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) | |
793 | super(_StoreAction, self).__init__( |
|
841 | super(_StoreAction, self).__init__( | |
@@ -877,7 +925,9 b' class _AppendAction(Action):' | |||||
877 | help=None, |
|
925 | help=None, | |
878 | metavar=None): |
|
926 | metavar=None): | |
879 | if nargs == 0: |
|
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 | if const is not None and nargs != OPTIONAL: |
|
931 | if const is not None and nargs != OPTIONAL: | |
882 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) |
|
932 | raise ValueError('nargs must be %r to supply const' % OPTIONAL) | |
883 | super(_AppendAction, self).__init__( |
|
933 | super(_AppendAction, self).__init__( | |
@@ -1281,6 +1331,17 b' class _ActionsContainer(object):' | |||||
1281 | for action in group._group_actions: |
|
1331 | for action in group._group_actions: | |
1282 | group_map[action] = title_group_map[group.title] |
|
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 | # add all actions to this container or their group |
|
1345 | # add all actions to this container or their group | |
1285 | for action in container._actions: |
|
1346 | for action in container._actions: | |
1286 | group_map.get(action, self)._add_action(action) |
|
1347 | group_map.get(action, self)._add_action(action) | |
@@ -2114,6 +2175,7 b' class ArgumentParser(_AttributeHolder, _ActionsContainer):' | |||||
2114 | def _get_value(self, action, arg_string): |
|
2175 | def _get_value(self, action, arg_string): | |
2115 | type_func = self._registry_get('type', action.type, action.type) |
|
2176 | type_func = self._registry_get('type', action.type, action.type) | |
2116 | if not hasattr(type_func, '__call__'): |
|
2177 | if not hasattr(type_func, '__call__'): | |
|
2178 | if not hasattr(type_func, '__bases__'): # classic classes | |||
2117 | msg = _('%r is not callable') |
|
2179 | msg = _('%r is not callable') | |
2118 | raise ArgumentError(action, msg % type_func) |
|
2180 | raise ArgumentError(action, msg % type_func) | |
2119 |
|
2181 |
General Comments 0
You need to be logged in to leave comments.
Login now