# Commits

committed 4f90b47

new files

• Participants
• Parent commits 9d61c57
• Branches legacy-trunk

# File Lib/Complex.py

`+# Complex numbers`
`+# ---------------`
`+`
`+# This module represents complex numbers as instances of the class Complex.`
`+# A Complex instance z has two data attribues, z.re (the real part) and z.im`
`+# (the imaginary part).  In fact, z.re and z.im can have any value -- all`
`+# arithmetic operators work regardless of the type of z.re and z.im (as long`
`+# as they support numerical operations).`
`+#`
`+# The following functions exist (Complex is actually a class):`
`+# Complex([re [,im]) -> creates a complex number from a real and an imaginary part`
`+# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)`
`+# Polar([r [,phi [,fullcircle]]]) ->`
`+#	the complex number z for which r == z.radius() and phi == z.angle(fullcircle)`
`+#	(r and phi default to 0)`
`+#`
`+# Complex numbers have the following methods:`
`+# z.abs() -> absolute value of z`
`+# z.radius() == z.abs()`
`+# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units`
`+# z.phi([fullcircle]) == z.angle(fullcircle)`
`+#`
`+# These standard functions and unary operators accept complex arguments:`
`+# abs(z)`
`+# -z`
`+# +z`
`+# not z`
`+# repr(z) == `z``
`+# str(z)`
`+# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero`
`+#            the result equals hash(z.re)`
`+# Note that hex(z) and oct(z) are not defined.`
`+#`
`+# These conversions accept complex arguments only if their imaginary part is zero:`
`+# int(z)`
`+# long(z)`
`+# float(z)`
`+#`
`+# The following operators accept two complex numbers, or one complex number`
`+# and one real number (int, long or float):`
`+# z1 + z2`
`+# z1 - z2`
`+# z1 * z2`
`+# z1 / z2`
`+# pow(z1, z2)`
`+# cmp(z1, z2)`
`+# Note that z1 % z2 and divmod(z1, z2) are not defined,`
`+# nor are shift and mask operations.`
`+#`
`+# The standard module math does not support complex numbers.`
`+# (I suppose it would be easy to implement a cmath module.)`
`+#`
`+# Idea:`
`+# add a class Polar(r, phi) and mixed-mode arithmetic which`
`+# chooses the most appropriate type for the result:`
`+# Complex for +,-,cmp`
`+# Polar   for *,/,pow`
`+`
`+`
`+import types, math`
`+`
`+if not hasattr(math, 'hypot'):`
`+	def hypot(x, y):`
`+		# XXX I know there's a way to compute this without possibly causing`
`+		# overflow, but I can't remember what it is right now...`
`+		return math.sqrt(x*x + y*y)`
`+	math.hypot = hypot`
`+`
`+twopi = math.pi*2.0`
`+halfpi = math.pi/2.0`
`+`
`+def IsComplex(obj):`
`+	return hasattr(obj, 're') and hasattr(obj, 'im')`
`+`
`+def Polar(r = 0, phi = 0, fullcircle = twopi):`
`+	phi = phi * (twopi / fullcircle)`
`+	return Complex(math.cos(phi)*r, math.sin(phi)*r)`
`+`
`+class Complex:`
`+`
`+	def __init__(self, re=0, im=0):`
`+		if IsComplex(re):`
`+			im = im + re.im`
`+			re = re.re`
`+		if IsComplex(im):`
`+			re = re - im.im`
`+			im = im.re`
`+		self.re = re`
`+		self.im = im`
`+`
`+	def __setattr__(self, name, value):`
`+		if hasattr(self, name):`
`+			raise TypeError, "Complex numbers have set-once attributes"`
`+		self.__dict__[name] = value`
`+`
`+	def __repr__(self):`
`+		if not self.im:`
`+			return 'Complex(%s)' % `self.re``
`+		else:`
`+			return 'Complex(%s, %s)' % (`self.re`, `self.im`)`
`+`
`+	def __str__(self):`
`+		if not self.im:`
`+			return `self.re``
`+		else:`
`+			return 'Complex(%s, %s)' % (`self.re`, `self.im`)`
`+`
`+	def __coerce__(self, other):`
`+		if IsComplex(other):`
`+			return self, other`
`+		return self, Complex(other)	# May fail`
`+`
`+	def __cmp__(self, other):`
`+		return cmp(self.re, other.re) or cmp(self.im, other.im)`
`+`
`+	def __hash__(self):`
`+		if not self.im: return hash(self.re)`
`+		mod = sys.maxint + 1L`
`+		return int((hash(self.re) + 2L*hash(self.im) + mod) % (2L*mod) - mod)`
`+`
`+	def __neg__(self):`
`+		return Complex(-self.re, -self.im)`
`+`
`+	def __pos__(self):`
`+		return self`
`+`
`+	def __abs__(self):`
`+		return math.hypot(self.re, self.im)`
`+		##return math.sqrt(self.re*self.re + self.im*self.im)`
`+`
`+`
`+	def __int__(self):`
`+		if self.im:`
`+			raise ValueError, "can't convert Complex with nonzero im to int"`
`+		return int(self.re)`
`+`
`+	def __long__(self):`
`+		if self.im:`
`+			raise ValueError, "can't convert Complex with nonzero im to long"`
`+		return long(self.re)`
`+`
`+	def __float__(self):`
`+		if self.im:`
`+			raise ValueError, "can't convert Complex with nonzero im to float"`
`+		return float(self.re)`
`+`
`+	def __nonzero__(self):`
`+		return not (self.re == self.im == 0)`
`+`
`+	abs = radius = __abs__`
`+`
`+	def angle(self, fullcircle = twopi):`
`+		return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)`
`+`
`+	phi = angle`
`+`
`+	def __add__(self, other):`
`+		return Complex(self.re + other.re, self.im + other.im)`
`+`
`+	__radd__ = __add__`
`+`
`+	def __sub__(self, other):`
`+		return Complex(self.re - other.re, self.im - other.im)`
`+`
`+	def __rsub__(self, other):`
`+		return Complex(other.re - self.re, other.im - self.im)`
`+`
`+	def __mul__(self, other):`
`+		return Complex(self.re*other.re - self.im*other.im,`
`+		               self.re*other.im + self.im*other.re)`
`+`
`+	__rmul__ = __mul__`
`+`
`+	def __div__(self, other):`
`+		# Deviating from the general principle of not forcing re or im`
`+		# to be floats, we cast to float here, otherwise division`
`+		# of Complex numbers with integer re and im parts would use`
`+		# the (truncating) integer division`
`+		d = float(other.re*other.re + other.im*other.im)`
`+		if not d: raise ZeroDivisionError, 'Complex division'`
`+		return Complex((self.re*other.re + self.im*other.im) / d,`
`+		               (self.im*other.re - self.re*other.im) / d)`
`+`
`+	def __rdiv__(self, other):`
`+		return other / self`
`+`
`+	def __pow__(self, n, z=None):`
`+		if z is not None:`
`+			raise TypeError, 'Complex does not support ternary pow()'`
`+		if IsComplex(n):`
`+			if n.im: raise TypeError, 'Complex to the Complex power'`
`+			n = n.re`
`+		r = pow(self.abs(), n)`
`+		phi = n*self.angle()`
`+		return Complex(math.cos(phi)*r, math.sin(phi)*r)`
`+	`
`+	def __rpow__(self, base):`
`+		return pow(base, self)`
`+`
`+`
`+# Everything below this point is part of the test suite`
`+`
`+def checkop(expr, a, b, value, fuzz = 1e-6):`
`+	import sys`
`+	print '       ', a, 'and', b,`
`+	try:`
`+		result = eval(expr)`
`+	except:`
`+		result = sys.exc_type`
`+	print '->', result`
`+	if (type(result) == type('') or type(value) == type('')):`
`+		ok = result == value`
`+	else:`
`+		ok = abs(result - value) <= fuzz`
`+	if not ok:`
`+		print '!!\t!!\t!! should be', value, 'diff', abs(result - value)`
`+`
`+`
`+def test():`
`+	testsuite = {`
`+		'a+b': [`
`+			(1, 10, 11),`
`+			(1, Complex(0,10), Complex(1,10)),`
`+			(Complex(0,10), 1, Complex(1,10)),`
`+			(Complex(0,10), Complex(1), Complex(1,10)),`
`+			(Complex(1), Complex(0,10), Complex(1,10)),`
`+		],`
`+		'a-b': [`
`+			(1, 10, -9),`
`+			(1, Complex(0,10), Complex(1,-10)),`
`+			(Complex(0,10), 1, Complex(-1,10)),`
`+			(Complex(0,10), Complex(1), Complex(-1,10)),`
`+			(Complex(1), Complex(0,10), Complex(1,-10)),`
`+		],`
`+		'a*b': [`
`+			(1, 10, 10),`
`+			(1, Complex(0,10), Complex(0, 10)),`
`+			(Complex(0,10), 1, Complex(0,10)),`
`+			(Complex(0,10), Complex(1), Complex(0,10)),`
`+			(Complex(1), Complex(0,10), Complex(0,10)),`
`+		],`
`+		'a/b': [`
`+			(1., 10, 0.1),`
`+			(1, Complex(0,10), Complex(0, -0.1)),`
`+			(Complex(0, 10), 1, Complex(0, 10)),`
`+			(Complex(0, 10), Complex(1), Complex(0, 10)),`
`+			(Complex(1), Complex(0,10), Complex(0, -0.1)),`
`+		],`
`+		'pow(a,b)': [`
`+			(1, 10, 1),`
`+			(1, Complex(0,10), 'TypeError'),`
`+			(Complex(0,10), 1, Complex(0,10)),`
`+			(Complex(0,10), Complex(1), Complex(0,10)),`
`+			(Complex(1), Complex(0,10), 'TypeError'),`
`+			(2, Complex(4,0), 16),`
`+		],`
`+		'cmp(a,b)': [`
`+			(1, 10, -1),`
`+			(1, Complex(0,10), 1),`
`+			(Complex(0,10), 1, -1),`
`+			(Complex(0,10), Complex(1), -1),`
`+			(Complex(1), Complex(0,10), 1),`
`+		],`
`+	}`
`+	exprs = testsuite.keys()`
`+	exprs.sort()`
`+	for expr in exprs:`
`+		print expr + ':'`
`+		t = (expr,)`
`+		for item in testsuite[expr]:`
`+			apply(checkop, t+item)`
`+	`
`+`
`+if __name__ == '__main__':`
`+	test()`

# File Lib/cgi.py

`+#!/usr/local/bin/python`
`+#`
`+# A class for wrapping the WWW Forms Common Gateway Interface (CGI) `
`+# Michael McLay, NIST  mclay@eeel.nist.gov  6/14/94`
`+# `
`+# modified by Steve Majewski <sdm7g@Virginia.EDU> 12/5/94 `
`+#`
`+`
`+# Several classes to parse the name/value pairs that are passed to `
`+# a server's CGI by GET, POST or PUT methods by a WWW FORM. This `
`+# module is based on Mike McLay's original cgi.py after discussing`
`+# changes with him and others on the comp.lang.python newsgroup, and`
`+# at the NIST Python workshop. `
`+#`
`+# The rationale for changes was:`
`+#    The original FormContent class was almost, but not quite like`
`+#    a dictionary object. Besides adding some extra access methods,`
`+#    it had a values() method with different arguments and semantics`
`+#    from the standard values() method of a mapping object. Also, `
`+#    it provided several different access methods that may be necessary`
`+#    or useful, but made it a little more confusing to figure out how`
`+#    to use. Also, we wanted to make the most typical cases the simplest`
`+#    and most convenient access methods. ( Most form fields just return`
`+#    a single value, and in practice, a lot of code was just assuming`
`+#    a single value and ignoring all others. On the other hand, the `
`+#    protocol allows multiple values to be returned. `
`+#`
`+#  The new base class (FormContentDict) is just like a dictionary.`
`+#  In fact, if you just want a dictionary, all of the stuff that was`
`+#  in __init__ has been extracted into a cgi.parse() function that will`
`+#  return the "raw" dictionary, but having a class allows you to customize `
`+#  it further. `
`+#   Mike McLay's original FormContent class is reimplemented as a `
`+#  subclass of FormContentDict.`
`+#   There are two additional sub-classes, but I'm not yet too sure `
`+#  whether they are what I want. `
`+# `
`+`
`+import string,regsub,sys,os,urllib`
`+# since os.environ may often be used in cgi code, we name it in this module.`
`+from os import environ`
`+`
`+`
`+def parse():`
`+	if environ['REQUEST_METHOD'] == 'POST':`
`+		qs = sys.stdin.read(string.atoi(environ['CONTENT_LENGTH']))`
`+		environ['QUERY_STRING'] = qs`
`+	else:`
`+		qs = environ['QUERY_STRING']`
`+	name_value_pairs = string.splitfields(qs, '&')`
`+	dict = {}`
`+	for name_value in name_value_pairs:`
`+		nv = string.splitfields(name_value, '=')`
`+		if len(nv) != 2:`
`+			continue`
`+		name = nv[0]`
`+		value = urllib.unquote(regsub.gsub('+',' ',nv[1]))`
`+		if len(value):`
`+			if dict.has_key (name):`
`+				dict[name].append(value)`
`+			else:`
`+				dict[name] = [value]`
`+	return dict`
`+`
`+`
`+`
`+# The FormContent constructor creates a dictionary from the name/value pairs`
`+# passed through the CGI interface.`
`+`
`+`
`+#`
`+#  form['key'] `
`+#  form.__getitem__('key') `
`+#  form.has_key('key')`
`+#  form.keys()`
`+#  form.values()`
`+#  form.items()`
`+#  form.dict`
`+`
`+class FormContentDict:`
`+	def __init__( self ):`
`+		self.dict = parse()`
`+		self.query_string = environ['QUERY_STRING']`
`+	def __getitem__(self,key):`
`+		return self.dict[key]`
`+	def keys(self):`
`+		return self.dict.keys()`
`+	def has_key(self, key):`
`+		return self.dict.has_key(key)`
`+	def values(self):`
`+		return self.dict.values()`
`+	def items(self):`
`+		return self.dict.items() `
`+	def __len__( self ):`
`+		return len(self.dict)`
`+`
`+`
`+# This is the "strict" single-value expecting version. `
`+# IF you only expect a single value for each field, then form[key]`
`+# will return that single value ( the [0]-th ), and raise an `
`+# IndexError if that expectation is not true. `
`+# IF you expect a field to have possible multiple values, than you`
`+# can use form.getlist( key ) to get all of the values. `
`+# values() and items() are a compromise: they return single strings`
`+#  where there is a single value, and lists of strings otherwise. `
`+`
`+class SvFormContentDict(FormContentDict):`
`+	def __getitem__( self, key ):`
`+		if len( self.dict[key] ) > 1 : `
`+			raise IndexError, 'expecting a single value' `
`+		return self.dict[key][0]`
`+	def getlist( self, key ):`
`+		return self.dict[key]`
`+	def values( self ):`
`+		lis = []`
`+		for each in self.dict.values() : `
`+			if len( each ) == 1 : `
`+				lis.append( each[0] )`
`+			else: lis.append( each )`
`+		return lis`
`+	def items( self ):`
`+		lis = []`
`+		for key,value in self.dict.items():`
`+			if len(value) == 1 :`
`+				lis.append( (key,value[0]) )`
`+			else:	lis.append( (key,value) )`
`+		return lis`
`+`
`+`
`+# And this sub-class is similar to the above, but it will attempt to `
`+# interpret numerical values. This is here as mostly as an example,`
`+# but I think the real way to handle typed-data from a form may be`
`+# to make an additional table driver parsing stage that has a table`
`+# of allowed input patterns and the output conversion types - it `
`+# would signal type-errors on parse, not on access. `
`+class InterpFormContentDict(SvFormContentDict):`
`+	def __getitem__( self, key ):`
`+		v = SvFormContentDict.__getitem__( self, key )`
`+		if v[0] in string.digits+'+-.' : `
`+			try:  return  string.atoi( v ) `
`+			except ValueError:`
`+				try:	return string.atof( v )`
`+				except ValueError: pass`
`+		return string.strip(v)`
`+	def values( self ):`
`+		lis = [] `
`+		for key in self.keys():`
`+			try:`
`+				lis.append( self[key] )`
`+			except IndexError:`
`+				lis.append( self.dict[key] )`
`+		return lis`
`+	def items( self ):`
`+		lis = [] `
`+		for key in self.keys():`
`+			try:`
`+				lis.append( (key, self[key]) )`
`+			except IndexError:`
`+				lis.append( (key, self.dict[key]) )`
`+		return lis`
`+`
`+`
`+# class FormContent parses the name/value pairs that are passed to a`
`+# server's CGI by GET, POST, or PUT methods by a WWW FORM. several `
`+# specialized FormContent dictionary access methods have been added `
`+# for convenience.`
`+`
`+# function                   return value`
`+#`
`+# form.keys()                     all keys in dictionary`
`+# form.has_key('key')             test keys existance`
`+# form[key]                       returns list associated with key`
`+# form.values('key')              key's list (same as form.[key])`
`+# form.indexed_value('key' index) nth element in key's value list`
`+# form.value(key)                 key's unstripped value `
`+# form.length(key)                number of elements in key's list`
`+# form.stripped(key)              key's value with whitespace stripped`
`+# form.pars()                     full dictionary `
`+`
`+`
`+`
`+class FormContent(FormContentDict):`
`+# This is the original FormContent semantics of values,`
`+# not the dictionary like semantics. `
`+	def values(self,key):`
`+		if self.dict.has_key(key):return self.dict[key]`
`+		else: return None`
`+	def indexed_value(self,key, location):`
`+		if self.dict.has_key(key):`
`+			if len (self.dict[key]) > location:`
`+				return self.dict[key][location]`
`+			else: return None`
`+		else: return None`
`+	def value(self,key):`
`+		if self.dict.has_key(key):return self.dict[key][0]`
`+		else: return None`
`+	def length(self,key):`
`+		return len (self.dict[key])`
`+	def stripped(self,key):`
`+		if self.dict.has_key(key):return string.strip(self.dict[key][0])`
`+		else: return None`
`+	def pars(self):`
`+		return self.dict`
`+`
`+`
`+`
`+`
`+`
`+`
`+def print_environ_usage():`
`+	print """`
`+<H3>These operating system environment variables could have been `
`+set:</H3> <UL>`
`+<LI>AUTH_TYPE`
`+<LI>CONTENT_LENGTH`
`+<LI>CONTENT_TYPE`
`+<LI>DATE_GMT`
`+<LI>DATE_LOCAL`
`+<LI>DOCUMENT_NAME`
`+<LI>DOCUMENT_ROOT`
`+<LI>DOCUMENT_URI`
`+<LI>GATEWAY_INTERFACE`
`+<LI>LAST_MODIFIED`
`+<LI>PATH`
`+<LI>PATH_INFO`
`+<LI>PATH_TRANSLATED`
`+<LI>QUERY_STRING`
`+<LI>REMOTE_ADDR`
`+<LI>REMOTE_HOST`
`+<LI>REMOTE_IDENT`
`+<LI>REMOTE_USER`
`+<LI>REQUEST_METHOD`
`+<LI>SCRIPT_NAME`
`+<LI>SERVER_NAME`
`+<LI>SERVER_PORT`
`+<LI>SERVER_PROTOCOL`
`+<LI>SERVER_ROOT`
`+<LI>SERVER_SOFTWARE`
`+</UL>`
`+"""`
`+`
`+def print_environ():`
`+	skeys = environ.keys()`
`+	skeys.sort()`
`+	print '<h3> The following environment variables were set by the CGI script: </H3>'`
`+	print '<dl>'`
`+	for key in skeys:`
`+		print '<dt>',key, '<dd>', environ[key]`
`+	print '</dl>' `
`+`
`+def print_form( form ):`
`+	print '<h3> The following name/value pairs were entered in the form:</h3>'`
`+	print '<dl>'`
`+	skeys = form.keys()`
`+	skeys.sort()`
`+	for key in skeys:`
`+		print '<dt>',key, ' : <i> ',escape(`type(form[key])`),' </i>','<dd>', form[key]`
`+	print '</dl>'`
`+`
`+def escape( s ):`
`+	return regsub.gsub( '<', '&lt;', regsub.gsub( '>' , '&gt;', s ))`
`+`
`+def test( what ):`
`+	label = escape(str(what))`
`+	print 'Content-type: text/html\n\n'`
`+	print '<HEADER>\n<TITLE>' + label + '</TITLE>\n</HEADER>\n'`
`+	print '<BODY>\n' `
`+	print "<H1>" + label +"</H1>\n"`
`+	form = what()`
`+	print_form( form )`
`+	print_environ()`
`+	print_environ_usage() `
`+	print '</body>'`
`+`
`+if __name__ == '__main__' : `
`+	test_classes = ( FormContent, FormContentDict, SvFormContentDict, InterpFormContentDict )`
`+	test( test_classes[0] )	# by default, test compatibility with `
`+				# old version, change index to test others.`

# File Lib/popen2.py

`+import os`
`+import sys`
`+import string`
`+`
`+MAXFD = 100	# Max number of file descriptors (os.getdtablesize()???)`
`+`
`+def popen2(cmd):`
`+	cmd = string.split(cmd)`
`+	p2cread, p2cwrite = os.pipe()`
`+	c2pread, c2pwrite = os.pipe()`
`+	pid = os.fork()`
`+	if pid == 0:`
`+		# Child`
`+		os.close(0)`
`+		os.close(1)`
`+		if os.dup(p2cread) <> 0:`
`+			sys.stderr.write('popen2: bad read dup\n')`
`+		if os.dup(c2pwrite) <> 1:`
`+			sys.stderr.write('popen2: bad write dup\n')`
`+		for i in range(3, MAXFD):`
`+			try:`
`+				os.close(i)`
`+			except:`
`+				pass`
`+		try:`
`+			os.execv(cmd[0], cmd)`
`+		finally:`
`+			os._exit(1)`
`+		# Shouldn't come here, I guess`
`+		os._exit(1)`
`+	os.close(p2cread)`
`+	tochild = os.fdopen(p2cwrite, 'w')`
`+	os.close(c2pwrite)`
`+	fromchild = os.fdopen(c2pread, 'r')`
`+	return fromchild, tochild`

# File Lib/rexec.py

`+# Implement restricted execution of Python code`
`+`
`+import __builtin__`
`+import new`
`+import os`
`+import sys`
`+import types`
`+`
`+def trace(fmt, *args):`
`+	if 0:`
`+		sys.stderr.write(fmt % args + '\n')`
`+`
`+def copydict(src, dst, exceptions = [], only = None):`
`+	if only is None:`
`+		for key in src.keys():`
`+			if key not in exceptions:`
`+				dst[key] = src[key]`
`+	else:`
`+		for key in only:`
`+			dst[key] = src[key]`
`+`
`+def copymodule(src, dst, exceptions = [], only = None):`
`+	copydict(src.__dict__, dst.__dict__, exceptions, only)`
`+`
`+safe_path = ['/ufs/guido/lib/python']`
`+safe_modules = ['array', 'math', 'regex', 'strop', 'time']`
`+unsafe_builtin_names = ['open', 'reload', '__import__',`
`+			'eval', 'execfile', 'dir', 'vars',`
`+			'raw_input', 'input']`
`+safe_posix_names = ['error', 'fstat', 'listdir', 'lstat', 'readlink', 'stat',`
`+		    'times', 'uname', 'getpid', 'getppid', 'getcwd',`
`+		    'getuid', 'getgid', 'geteuid', 'getegid']`
`+`
`+safe_sys = new.module('sys')`
`+safe_sys.modules = {}`
`+safe_sys.modules['sys'] = safe_sys`
`+safe_sys.path = safe_path[:]`
`+safe_sys.argv = ['-']`
`+safe_sys.builtin_module_names = safe_modules[:] + ['posix']`
`+safe_sys.builtin_module_names.sort()`
`+safe_sys.copyright = sys.copyright`
`+safe_sys.version = sys.version + ' [restricted mode]'`
`+safe_sys.exit = sys.exit`
`+`
`+def new_module(name):`
`+	safe_sys.modules[name] = m = new.module(name)`
`+	return m`
`+`
`+safe_builtin = new_module('__builtin__')`
`+copymodule(__builtin__, safe_builtin, unsafe_builtin_names)`
`+`
`+safe_main = new_module('__main__')`
`+`
`+safe_posix = new_module('posix')`
`+import posix`
`+copymodule(posix, safe_posix, None, safe_posix_names)`
`+safe_posix.environ = {}`
`+copydict(posix.environ, safe_posix.environ)`
`+`
`+safe_types = new_module('types')`
`+copymodule(types, safe_types)`
`+`
`+def safe_import(name):`
`+	if safe_sys.modules.has_key(name):`
`+		return safe_sys.modules[name]`
`+	if name in safe_modules:`
`+		temp = {}`
`+		exec "import "+name in temp`
`+		m = new_module(name)`
`+		copymodule(temp[name], m)`
`+		return m`
`+	for dirname in safe_path:`
`+		filename = os.path.join(dirname, name + '.py')`
`+		try:`
`+			f = open(filename, 'r')`
`+			f.close()`
`+		except IOError:`
`+			continue`
`+		m = new_module(name)`
`+		rexecfile(filename, m.__dict__)`
`+		return m`
`+	raise ImportError, name`
`+safe_builtin.__import__ = safe_import`
`+`
`+def safe_open(file, mode = 'r'):`
`+	if type(file) != types.StringType or type(mode) != types.StringType:`
`+		raise TypeError, 'open argument(s) must be string(s)'`
`+	if mode not in ('r', 'rb'):`
`+		raise IOError, 'open for writing not allowed'`
`+	if '/' in file:`
`+		raise IOError, 'open pathname not allowed'`
`+	return open(file, mode)`
`+safe_builtin.open = safe_open`
`+`
`+def safe_dir(object = safe_main):`
`+	keys = object.__dict__.keys()`
`+	keys.sort()`
`+	return keys`
`+safe_builtin.dir = safe_dir`
`+`
`+def safe_vars(object = safe_main):`
`+	keys = safe_dir(object)`
`+	dict = {}`
`+	copydict(object.__dict__, dict, None, keys)`
`+	return dict`
`+safe_builtin.vars = safe_vars`
`+`
`+`
`+def exterior():`
`+	"""Return env of caller's caller, as triple: (name, locals, globals).`
`+`
`+	Name will be None if env is __main__, and locals will be None if same`
`+	as globals, ie local env is global env."""`
`+`
`+	import sys, __main__`
`+`
`+	bogus = 'bogus'			# A locally usable exception`
`+	try: raise bogus		# Force an exception`
`+	except bogus:`
`+		at = sys.exc_traceback.tb_frame.f_back # The external frame.`
`+		if at.f_back: at = at.f_back # And further, if any.`
`+		where, globals, locals = at.f_code, at.f_globals, at.f_locals`
`+		if locals == globals:	# Exterior is global?`
`+			locals = None`
`+		if where:`
`+			where = where.co_name`
`+		return (where, locals, globals)`
`+`
`+`
`+def rexec(str, globals = None, locals = None):`
`+	trace('rexec(%s, ...)', `str`)`
`+	if globals is None:`
`+		globals = locals = exterior()[2]`
`+	elif locals is None:`
`+		locals = globals`
`+	globals['__builtins__'] = safe_builtin.__dict__`
`+	safe_sys.stdout = sys.stdout`
`+	safe_sys.stderr = sys.stderr`
`+	exec str in globals, locals`
`+`
`+def rexecfile(file, globals = None, locals = None):`
`+	trace('rexecfile(%s, ...)', `file`)`
`+	if globals is None:`
`+		globals = locals = exterior()[2]`
`+	elif locals is None:`
`+		locals = globals`
`+	globals['__builtins__'] = safe_builtin.__dict__`
`+	safe_sys.stdout = sys.stdout`
`+	safe_sys.stderr = sys.stderr`
`+	return execfile(file, globals, locals)`
`+`
`+def reval(str, globals = None, locals = None):`
`+	trace('reval(%s, ...)', `str`)`
`+	if globals is None:`
`+		globals = locals = exterior()[2]`
`+	elif locals is None:`
`+		locals = globals`
`+	globals['__builtins__'] = safe_builtin.__dict__`
`+	safe_sys.stdout = sys.stdout`
`+	safe_sys.stderr = sys.stderr`
`+	return eval(str, globals, locals)`
`+safe_builtin.eval = reval`
`+`
`+`
`+def test():`
`+	import traceback`
`+	g = {}`
`+	while 1:`
`+		try:`
`+			s = raw_input('--> ')`
`+		except EOFError:`
`+			break`
`+		try:`
`+			try:`
`+				c = compile(s, '', 'eval')`
`+			except:`
`+				rexec(s, g)`
`+			else:`
`+				print reval(c, g)`
`+		except:`
`+			traceback.print_exc()`
`+`
`+if __name__ == '__main__':`
`+	test()`