parameter.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Tue Apr 2 18:31:47 2013
  4. @author: pietro
  5. """
  6. from __future__ import (nested_scopes, generators, division, absolute_import,
  7. with_statement, print_function, unicode_literals)
  8. import re
  9. from grass.pygrass.functions import docstring_property
  10. from grass.pygrass.modules.interface.read import GETTYPE, element2dict, DOC
  11. # TODO add documentation
  12. class Parameter(object):
  13. """The Parameter object store all information about a parameter of module.
  14. It is possible to set parameter of command using this object.
  15. """
  16. def __init__(self, xparameter=None, diz=None):
  17. self._value = None
  18. diz = element2dict(xparameter) if xparameter is not None else diz
  19. if diz is None:
  20. raise TypeError('Xparameter or diz are required')
  21. self.name = diz['name']
  22. self.required = True if diz['required'] == 'yes' else False
  23. self.multiple = True if diz['multiple'] == 'yes' else False
  24. # check the type
  25. if diz['type'] in GETTYPE:
  26. self.type = GETTYPE[diz['type']]
  27. self.typedesc = diz['type']
  28. else:
  29. raise TypeError('New type: %s, ignored' % diz['type'])
  30. self.description = diz.get('description', None)
  31. self.keydesc, self.keydescvalues = diz.get('keydesc', (None, None))
  32. #
  33. # values
  34. #
  35. if 'values' in diz:
  36. try:
  37. # Check for integer ranges: "3-30" or float ranges: "0.0-1.0"
  38. isrange = re.match("(?P<min>-*\d+.*\d*)-(?P<max>\d+.*\d*)",
  39. diz['values'][0])
  40. if isrange:
  41. mn, mx = isrange.groups()
  42. self.min, self.max = float(mn), float(mx)
  43. self.values = None
  44. self.isrange = diz['values'][0]
  45. # No range was found
  46. else:
  47. self.values = [self.type(i) for i in diz['values']]
  48. self.isrange = False
  49. except TypeError:
  50. self.values = [self.type(i) for i in diz['values']]
  51. self.isrange = False
  52. #
  53. # default
  54. #
  55. if 'default' in diz:
  56. if self.multiple or self.keydescvalues:
  57. self.default = [self.type(v)
  58. for v in diz['default'].split(',')]
  59. else:
  60. self.default = self.type(diz['default'])
  61. self._value = self.default
  62. else:
  63. self.default = None
  64. self.guisection = diz.get('guisection', None)
  65. #
  66. # gisprompt
  67. #
  68. if 'gisprompt' in diz and diz['gisprompt']:
  69. self.typedesc = diz['gisprompt'].get('prompt', '')
  70. self.input = False if diz['gisprompt']['age'] == 'new' else True
  71. else:
  72. self.input = True
  73. def _get_value(self):
  74. return self._value
  75. def _set_value(self, value):
  76. values_error = 'The Parameter <%s>, must be a python list ' \
  77. 'containing one or more of the following values: %r'
  78. if value is None:
  79. self._value = value
  80. elif isinstance(value, list) or isinstance(value, tuple):
  81. if self.multiple or self.keydescvalues:
  82. # check each value
  83. self._value = [self.type(val) for val in value]
  84. else:
  85. str_err = 'The Parameter <%s> does not accept multiple inputs'
  86. raise TypeError(str_err % self.name)
  87. elif self.typedesc == 'all':
  88. self._value = value
  89. elif isinstance(value, self.type):
  90. if hasattr(self, 'values'):
  91. if self.type in (float, int):
  92. if self.min <= value <= self.max:
  93. self._value = value
  94. else:
  95. err_str = 'The Parameter <%s>, must be: %g<=value<=%g'
  96. raise ValueError(err_str % (self.name, self.min,
  97. self.max))
  98. elif value in self.values:
  99. self._value = value
  100. else:
  101. raise ValueError(values_error % (self.name, self.values))
  102. else:
  103. self._value = value
  104. elif self.type is str and isinstance(value, unicode):
  105. if hasattr(self, 'values'):
  106. if value in self.values:
  107. self._value = str(value)
  108. else:
  109. raise ValueError(values_error % (self.name, self.values))
  110. else:
  111. self._value = str(value)
  112. elif self.type is str and isinstance(value, str):
  113. if hasattr(self, 'values'):
  114. if value in self.values:
  115. self._value = value
  116. else:
  117. raise ValueError(values_error % (self.name, self.values))
  118. else:
  119. self._value = value
  120. else:
  121. str_err = 'The Parameter <%s>, require: %s, get: %s instead'
  122. raise TypeError(str_err % (self.name, self.typedesc, type(value)))
  123. # here the property function is used to transform value in an attribute
  124. # in this case we define which function must be use to get/set the value
  125. value = property(fget=_get_value, fset=_set_value,
  126. doc="Set or obtain value")
  127. def get_bash(self):
  128. """Prova"""
  129. if isinstance(self._value, list) or isinstance(self._value, tuple):
  130. value = ','.join([str(v) for v in self._value])
  131. else:
  132. value = str(self._value)
  133. return """%s=%s""" % (self.name, value)
  134. def get_python(self):
  135. """Prova"""
  136. if not self.value:
  137. return ''
  138. return """%s=%r""" % (self.name, self._value)
  139. def __str__(self):
  140. return self.get_bash()
  141. def __repr__(self):
  142. str_repr = "Parameter <%s> (required:%s, type:%s, multiple:%s)"
  143. return str_repr % (self.name,
  144. "yes" if self.required else "no",
  145. self.type if self.type in (
  146. 'raster', 'vector') else self.typedesc,
  147. "yes" if self.multiple else "no")
  148. @docstring_property(__doc__)
  149. def __doc__(self):
  150. """Return the docstring of the parameter
  151. {name}: {default}{required}{multi}{ptype}
  152. {description}{values}"","""
  153. if hasattr(self, 'values'):
  154. if self.isrange:
  155. vals = self.isrange
  156. else:
  157. vals = ', '.join([repr(val) for val in self.values])
  158. else:
  159. vals = False
  160. if self.keydescvalues:
  161. keydescvals = "\n (%s)" % ', '.join(self.keydescvalues)
  162. return DOC['param'].format(name=self.name,
  163. default=repr(self.default) + ', ' if self.default else '',
  164. required='required, ' if self.required else 'optional, ',
  165. multi='multi' if self.multiple else '',
  166. ptype=self.typedesc, description=self.description,
  167. values='\n Values: {0}'.format(vals) if vals else '',
  168. keydescvalues= keydescvals if self.keydescvalues else '')