comparison flagReader.py @ 0:febfdc79550b

moved repository to Assembla
author catherine@DellZilla.myhome.westell.com
date Wed, 05 Mar 2008 12:16:19 -0500
parents
children f807c5cfa0de
comparison
equal deleted inserted replaced
-1:000000000000 0:febfdc79550b
1 """Defines and parses UNIX-style flags to modify command arguments.
2
3 print flagReader.FlagSet.parse.__doc__ for usage examples.
4 """
5
6 import re
7
8 class Flag(object):
9 def __init__(self, name, abbrev=None, nargs=0):
10 """Flag(name, abbrev=None, nargs=0) : Defines a flag.
11
12 name: the full name of the flag (double-dash form)
13 abbrev: the single-letter abbreviated form of the flag; defaults to
14 nargs: number of arguments expected after the flag"""
15
16 self.name = name
17 self.abbrev = abbrev or name[0]
18 self.fullabbrev = '-%s' % (self.abbrev)
19 self.fullname = '--%s' % (name)
20 self.nargs = nargs
21
22 class FlagSet(object):
23 def __init__(self, flags):
24 if not issubclass(type(flags), list):
25 raise TypeError, 'Argument must be a list'
26 self.flags = flags
27 self.lookup = {}
28 for flag in self.flags:
29 self.lookup[flag.abbrev] = flag
30 self.lookup[flag.fullabbrev] = flag
31 self.lookup[flag.fullname] = flag
32 self.abbrevPattern = re.compile('^-([%s]+)$' % (''.join(f.abbrev for f in flags)))
33 def parse(self, arg):
34 """
35 Finds flags; returns {flag: (values, if any)} and the remaining argument.
36
37 >>> f = FlagSet([Flag('foo'), Flag('bar'), Flag('gimmea', nargs=1)])
38 >>> f.parse('-fb')
39 ({'foo': [], 'bar': []}, '')
40 >>> f.parse('no flags')
41 ({}, 'no flags')
42 >>> f.parse('-f blah')
43 ({'foo': []}, 'blah')
44 >>> f.parse('--bar')
45 ({'bar': []}, '')
46 >>> f.parse('--bar -f')
47 ({'foo': [], 'bar': []}, '')
48 >>> f.parse('--notaflag')
49 ({}, '--notaflag')
50 >>> f.parse('')
51 ({}, '')
52 >>> f.parse('--gimmea bee -f and then some other stuff')
53 ({'gimmea': ['bee'], 'foo': []}, 'and then some other stuff')
54 >>> f.parse('hidden -bar')
55 ({}, 'hidden -bar')
56 >>> f.parse('-g myarg -b')
57 ({'gimmea': ['myarg'], 'bar': []}, '')
58 """
59 result = {}
60 words = arg.split()
61 while words:
62 word = words[0]
63 flag = self.lookup.get(word)
64 if flag:
65 result[flag.name] = []
66 words.pop(0)
67 for arg in range(flag.nargs):
68 try:
69 result[flag.name].append(words.pop(0))
70 except IndexError: # there aren't as many args as we expect
71 raise IndexError, '%s expects %d arguments' % (word, flag.nargs)
72 continue # on to next word
73 smashedAbbrevs = self.abbrevPattern.search(word)
74 if smashedAbbrevs:
75 for abbrev in smashedAbbrevs.group(1):
76 result[self.lookup[abbrev].name] = []
77 words.pop(0)
78 continue # on to next word
79 #if you get to here, word[0] does not denote options
80 break
81 return result, ' '.join(words)
82
83 def _test():
84 import doctest
85 doctest.testmod()
86
87 if __name__ == '__main__':
88 _test()