import re, sys class SecurityError(Exception): pass from types import * pat_fl = r'[-+]?(((((\d+)?[.]\d+|\d+[.])|\d+)[eE][+-]?\d+)|((\d+)?[.]\d+|\d+[.]))' re_float = re.compile(pat_fl+'$') re_zero = '[+-]?0$' pat_int = r'[-+]?[1-9]\d*' re_int = re.compile(pat_int+'$') pat_flint = '(%s|%s)' % (pat_fl, pat_int) # float or int re_long = re.compile(r'[-+]?[1-9]\d*[lL]'+'$') re_hex = re.compile(r'([-+]?)(0[xX])([0-9a-fA-F]+)'+'$') re_oct = re.compile(r'([-+]?)(0)([0-7]+)'+'$') pat_complex = r'(%s)?[-+]%s[jJ]' % (pat_flint, pat_flint) re_complex = re.compile(pat_complex+'$') pat_complex2 = '(%s):(%s)' % (pat_flint, pat_flint) re_complex2 = re.compile(pat_complex2+'$') def aton(s): #-- massage the string slightly s = s.strip() while s[0] == '(' and s[-1] == ')': # remove optional parens s = s[1:-1] #-- test for cases if re.match(re_zero, s): return 0 if re.match(re_float, s): return float(s) if re.match(re_long, s): return long(s) if re.match(re_int, s): return int(s) m = re.match(re_hex, s) if m: n = long(m.group(3),16) if n < sys.maxint: n = int(n) if m.group(1)=='-': n *= -1 return n m = re.match(re_oct, s) if m: n = long(m.group(3),8) if n < sys.maxint: n = int(n) if m.group(1)=='-': n *= -1 return n if re.match(re_complex, s): return complex(s) if re.match(re_complex2, s): r, i = s.split(':') return complex(float(r), float(i)) raise SecurityError, \ "Malicious string '%s' passed to to_number()'d" % s # we use ntoa() instead of repr() to ensure we have a known output format def ntoa(n): "Convert a number to a string without calling repr()" if isinstance(n,IntType): s = "%d" % n elif isinstance(n,LongType): s = "%ldL" % n elif isinstance(n,FloatType): s = "%.17g" % n if '.' not in s and 'e' not in s: # ensure a '.' s += '.' elif isinstance(n,ComplexType): # these are always used as doubles, so it doesn't # matter if the '.' shows up s = "%.17g:%.17g" % (n.real,n.imag) else: raise ValueError, \ "Unknown numeric type: %s" % repr(n) return s def to_number(s): "Convert a string to a number without calling eval()" try: return aton(s) except SecurityError: return None