parseargs.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # Written by Bill Bumgarner and Bram Cohen
  2. # see LICENSE.txt for license information
  3. from types import *
  4. from cStringIO import StringIO
  5. def splitLine(line, COLS=80, indent=10):
  6. indent = " " * indent
  7. width = COLS - (len(indent) + 1)
  8. if indent and width < 15:
  9. width = COLS - 2
  10. indent = " "
  11. s = StringIO()
  12. i = 0
  13. for word in line.split():
  14. if i == 0:
  15. s.write(indent+word)
  16. i = len(word)
  17. continue
  18. if i + len(word) >= width:
  19. s.write('\n'+indent+word)
  20. i = len(word)
  21. continue
  22. s.write(' '+word)
  23. i += len(word) + 1
  24. return s.getvalue()
  25. def formatDefinitions(options, COLS, presets = {}):
  26. s = StringIO()
  27. for (longname, default, doc) in options:
  28. s.write('--' + longname + ' <arg>\n')
  29. default = presets.get(longname, default)
  30. if type(default) in (IntType, LongType):
  31. try:
  32. default = int(default)
  33. except:
  34. pass
  35. if default is not None:
  36. doc += ' (defaults to ' + repr(default) + ')'
  37. s.write(splitLine(doc,COLS,10))
  38. s.write('\n\n')
  39. return s.getvalue()
  40. def usage(str):
  41. raise ValueError(str)
  42. def defaultargs(options):
  43. l = {}
  44. for (longname, default, doc) in options:
  45. if default is not None:
  46. l[longname] = default
  47. return l
  48. def parseargs(argv, options, minargs = None, maxargs = None, presets = {}):
  49. config = {}
  50. longkeyed = {}
  51. for option in options:
  52. longname, default, doc = option
  53. longkeyed[longname] = option
  54. config[longname] = default
  55. for longname in presets.keys(): # presets after defaults but before arguments
  56. config[longname] = presets[longname]
  57. options = []
  58. args = []
  59. pos = 0
  60. while pos < len(argv):
  61. if argv[pos][:2] != '--':
  62. args.append(argv[pos])
  63. pos += 1
  64. else:
  65. if pos == len(argv) - 1:
  66. usage('parameter passed in at end with no value')
  67. key, value = argv[pos][2:], argv[pos+1]
  68. pos += 2
  69. if not longkeyed.has_key(key):
  70. usage('unknown key --' + key)
  71. longname, default, doc = longkeyed[key]
  72. try:
  73. t = type(config[longname])
  74. if t is NoneType or t is StringType:
  75. config[longname] = value
  76. elif t in (IntType, LongType):
  77. config[longname] = long(value)
  78. elif t is FloatType:
  79. config[longname] = float(value)
  80. else:
  81. assert 0
  82. except ValueError, e:
  83. usage('wrong format of --%s - %s' % (key, str(e)))
  84. for key, value in config.items():
  85. if value is None:
  86. usage("Option --%s is required." % key)
  87. if minargs is not None and len(args) < minargs:
  88. usage("Must supply at least %d args." % minargs)
  89. if maxargs is not None and len(args) > maxargs:
  90. usage("Too many args - %d max." % maxargs)
  91. return (config, args)
  92. def test_parseargs():
  93. assert parseargs(('d', '--a', 'pq', 'e', '--b', '3', '--c', '4.5', 'f'), (('a', 'x', ''), ('b', 1, ''), ('c', 2.3, ''))) == ({'a': 'pq', 'b': 3, 'c': 4.5}, ['d', 'e', 'f'])
  94. assert parseargs([], [('a', 'x', '')]) == ({'a': 'x'}, [])
  95. assert parseargs(['--a', 'x', '--a', 'y'], [('a', '', '')]) == ({'a': 'y'}, [])
  96. try:
  97. parseargs([], [('a', 'x', '')])
  98. except ValueError:
  99. pass
  100. try:
  101. parseargs(['--a', 'x'], [])
  102. except ValueError:
  103. pass
  104. try:
  105. parseargs(['--a'], [('a', 'x', '')])
  106. except ValueError:
  107. pass
  108. try:
  109. parseargs([], [], 1, 2)
  110. except ValueError:
  111. pass
  112. assert parseargs(['x'], [], 1, 2) == ({}, ['x'])
  113. assert parseargs(['x', 'y'], [], 1, 2) == ({}, ['x', 'y'])
  114. try:
  115. parseargs(['x', 'y', 'z'], [], 1, 2)
  116. except ValueError:
  117. pass
  118. try:
  119. parseargs(['--a', '2.0'], [('a', 3, '')])
  120. except ValueError:
  121. pass
  122. try:
  123. parseargs(['--a', 'z'], [('a', 2.1, '')])
  124. except ValueError:
  125. pass