# Copyright (C) 2002, 2003 by Intevation GmbH # Authors: # Thomas Arendsen Hein # # This program is free software under the GPL (>=v2) # Read the file COPYING coming with the software for details. """ Range class for Scientific Parameter """ __version__ = "$Revision: 1.15 $" # $Source: /greaterrepository/sciparam/SciParam/range.py,v $ # $Id: range.py,v 1.15 2003/09/29 16:39:19 thomas Exp $ import re import types _inf = float('1e1000') # FIXME: hack for infinite class Range: number_re = '(?P<%s>-?(\d*\.?\d*([eE][\-+]?\d+)?|oo))' brace_re = '(?P<%s>[][])' range_re = '^' + brace_re % 'left' + number_re % 'begin' + \ ';' + number_re % 'end' + brace_re % 'right' + '$' parse_range = re.compile(range_re) def __init__(self, range=None): self._SetRange(range) def _SetRange(self, range): if isinstance(range, Range): self._SetRange(range.GetRange()) elif range in [None, '']: self._SetRange(']-oo;oo[') elif type(range) == types.TupleType: if (len(range) == 4 and range[0] in ['[', ']'] and range[3] in ['[', ']']): self._left = range[0] self._begin = self.float(range[1]) self._end = self.float(range[2]) self._right = range[3] if (self._begin > self._end or (self._begin == self._end and (self._left != '[' or self._right != ']'))): raise ValueError("illegal range: %s" % (range,)) else: raise ValueError("can't parse range: %r" % (range,)) else: self._range = range match = self.parse_range.match(self._range) if match: self._SetRange((match.group('left'), match.group('begin'), match.group('end'), match.group('right'))) else: raise ValueError("can't parse range: %s" % (range,)) def GetRange(self): """return internal representation of range 4-tuple ('[' or ']', begin(float), end(float), '[' or ']') """ return (self._left, self._begin, self._end, self._right) def float(self, value): """convert string or number to float""" if value == 'oo': return _inf elif value == '-oo': return -_inf else: return float(value) def _float2string(self, value): """convert float value to string (minus) infinity will be converted to (-)oo, scientific notation will be used if necessary. """ if value == _inf: return 'oo' elif value == -_inf: return '-oo' else: return "%g" % (value,) def string(self, range): """convert internal representation to string""" left, begin, end, right = range return "%s%s;%s%s" % (left, self._float2string(begin), self._float2string(end), right) def __contains__(self, value): if self._left == ']': contains = value > self._begin else: contains = value >= self._begin if self._right == '[': contains = contains and (value < self._end) else: contains = contains and (value <= self._end) return contains def __eq__(self, other): return (self.GetRange() == other.GetRange()) def __ne__(self, other): return not self.__eq__(other) def __str__(self): return self.string(self.GetRange()) def _test(): range1 = Range(']0;99]') print 'range1 =', range1, range1.GetRange() for i in [-0.1, 0, 0.1, 9.9, 99, 99.9]: print '%4.1f in range1 =' % i, i in range1 range2 = Range(']-oo;10[') print 'range2 =', range2, range2.GetRange() for i in [-0.1, 0, 0.1, 9.9, 10, 10.1]: print '%4.1f not in range2 =' % i, i not in range2 range3 = Range(']1e-1;1E2]') print 'range3 =', range3, range3.GetRange() for i in [0, 0.1, 0.11, 10, 100, 101]: print '%4.1f not in range3 =' % i, i not in range3 print 'range3 != range2 =', range3 != range2 print 'range3 != Range("]1e-1;1E2]") =', range3 != Range("]1e-1;1E2]") range4 = Range('') print 'range4 =', range4, range4.GetRange() range5 = Range(']0;99E+00]') print 'range5 =', range5, range5.GetRange() range6 = Range(']0;99E+01]') print 'range6 =', range6, range6.GetRange() range7 = Range(']0;99E-01]') print 'range7 =', range7, range7.GetRange() if __name__ == "__main__": _test()