source: branches/active/character_customization/game/parpg/common/optionparser.py @ 758

Revision 736, 6.0 KB checked in by aspidites, 9 years ago (diff)

Patch by Aspidites:

  • renamed scripts package to parpg
  • renamed parpg module to application
  • removed packaging and other related files (kept locally for reference, will reintroduce similar scripts to resolve bug #275
  • updated all import statements to respect changes above
  • Property svn:mime-type set to text/plain
Line 
1#-------------------------------------------------------------------------------
2# Copyright (c) 2010 M. George Hansen.
3#
4# optionparser is free software: you can redistribute it and/or modify it under
5# the terms of the GNU General Public License as published by the Free Software
6# Foundation, either version 3 of the License, or (at your option) any later
7# version.
8#
9# optionparser is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
12# details.
13#
14# You should have received a copy of the GNU General Public License along with
15# optionparser.  If not, see <http://www.gnu.org/licenses/>.
16#-------------------------------------------------------------------------------
17"""
18:Original Author: Russ Cox <rsc@plan9.bell-labs.com>
19:Modified By: M. George Hansen <technopolitica@gmail.com>
20
21Usage:
22------
23>>> import sys
24>>> usagemessage=\
25... '''usage: example.py [-h] [-f FILE] [-n N] [-q] who where
26...     -h, --help                  show this help message
27...     -f FILE, --file=FILE        write report to FILE
28...     -n N, --num=N               print N copies of the report
29...     -q, --quiet                 don't print status messages to stdout
30... '''
31>>> def main():
32...     opt = OptionParser(usage=usagemessage)
33...     report = 'default.file'
34...     ncopies = 1
35...     verbose = 1
36...     for o in opt:
37...         if o=='-f' or o=='--file':
38...             report = opt.optarg()
39...         elif o=='-n' or o=='--num':
40...             ncopies = opt.optarg(opt.typecast(int, 'integer'))
41...         elif o=='-q' or o=='--quiet':
42...             verbose = 0
43...         else:
44...             opt.error('unknown option '+o)
45...     if len(opt.args()) != 2:
46...         opt.error('incorrect argument count')
47...     print 'report=%s, ncopies=%s verbose=%s' % (report, ncopies, verbose)
48...     print 'arguments: ', opt.args()
49...
50"""
51from __future__ import generators, print_function
52import sys
53import os.path
54import re
55
56class OptionError(Exception):
57    pass
58
59class OptionParser:
60    short_option_re = re.compile(r'^\s*-([A-Za-z]+)\s*$')
61    long_option_re = re.compile(
62        r'^\s*(--[A-Za-z][A-Za-z-]+)(?:\s*|=([^\s]*)\s*)$'
63    )
64   
65    def __init__(self, args=None, prog=None, usage='', version=''):
66        if (prog is None):
67            self.prog = os.path.basename(sys.argv[0])
68        else:
69            self.prog = prog
70        if (args is None):
71            self.args = sys.argv[1:]
72        else:
73            self.args = args
74        self.usage = usage.format(prog=self.prog)
75        self.version = '{prog} version {version}'.format(prog=self.prog,
76                                                         version=version)
77        self.current_option = None
78   
79    def __iter__(self):
80        program_arguments = []
81        while len(self.args) > 0:
82            arg = self.args.pop(0)
83            if (self.short_option_re.match(arg)):
84                # next token is one or more short options
85                match = self.short_option_re.match(arg)
86                options = ['-{0}'.format(abv) for abv in match.group(1)]
87                for opt in options:
88                    self.current_option = opt
89                    yield opt
90            elif (self.long_option_re.match(arg)):
91                # next token is a long option that may have its argument
92                # attached
93                match = self.long_option_re.match(arg)
94                option = match.group(1)
95                self.current_option = option
96                attached_arg = match.group(2)
97                if (attached_arg is not None):
98                    self.args.insert(0, attached_arg)
99                yield option
100            else:
101                program_arguments.append(arg)
102        self.current_option = None
103        self.args = program_arguments
104        while True:
105            raise StopIteration
106   
107    def get_next_option_arg(self, type_=str):
108        if (self.current_option is not None):
109            try:
110                arg = self.args.pop(0)
111            except IndexError:
112                arg = None
113            if (arg is None or self.short_option_re.match(arg) or
114                self.long_option_re.match(arg)):
115                message = '{0} option expected a {1} argument but got nothing'
116                message = message.format(
117                    self.current_option,
118                    getattr(type_, '__name__', type_)
119                )
120                self.error(message)
121        else:
122            message = 'no option is currently being parsed'
123            raise OptionError(message)
124       
125        try:
126            result = type_(arg)
127        except ValueError:
128            message = '''{0} expected a {1} argument but was unable to type
129cast "{2}"'''
130            message = message.format(
131                self.current_option,
132                getattr(type_, '__name__', type_),
133                arg
134            )
135            self.error(message)
136        return result
137   
138    def get_next_prog_arg(self, type_=str):
139        try:
140            arg = self.args.pop(0)
141        except IndexError:
142            arg = None
143        if (arg is None or self.short_option_re.match(arg) or
144            self.long_option_re.match(arg)):
145            message = 'expected a {0} argument but got nothing'
146            message = message.format(getattr(type_, '__name__', type_))
147            raise OptionError(message)
148        try:
149            result = type_(arg)
150        except ValueError:
151            message = '''{0} expected a {1} argument but was unable to type
152cast "{2}"'''
153            message = message.format(
154                self.current_option,
155                getattr(type_, '__name__', type_),
156                arg
157            )
158            self.error(message)
159        return result
160   
161    def error(self, message):
162        if (self.usage is not None):
163            print('option error: {0}\n\n{1}'.format(message, self.usage),
164                  file=sys.stderr)
165            sys.exit(0)
166        else:
167            raise OptionError(message)
Note: See TracBrowser for help on using the repository browser.