changeset 52:a5beba1b4611 pytave-dictionaries

Dictionaries
author David Grundberg <individ@acc.umu.se>
date Thu, 04 Jun 2009 16:20:18 +0200
parents b001edc0f81a
children 9180ce65a7bd 7f0ed7b5296b
files package/pytave.py test/test.py
diffstat 2 files changed, 104 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/package/pytave.py	Wed Jun 03 16:41:44 2009 +0200
+++ b/package/pytave.py	Thu Jun 04 16:20:18 2009 +0200
@@ -21,6 +21,7 @@
 """Python to Octave bridge"""
 
 import _pytave
+import UserDict
 import sys
 
 arg0 = sys.argv[0]
@@ -148,46 +149,31 @@
 	"""See Octave documentation"""
 	return _pytave.feval(1, "path", paths)[0]
 
-def getvar(name, fglobal = False):
-	 """Queries a variable by name from the current Octave scope.
-	 This is pretty much equivalent to calling eval(name), but is
-	 much faster because the Octave parser is bypassed. 
-	 
-	 global specifies that a global variable should be looked up;
-	 otherwise, local variable (in the current scope) is always
-	 searched for.
+class _VariablesDict(UserDict.DictMixin):
+	def __init__(self, global_variables):
+		self.global_variables = global_variables
 
-	 If the variable is not defined, VarNameError exception is raised.
-	 """
-	 return _pytave.getvar(name, fglobal)
-
-def setvar(name, val, fglobal = False):
-	 """Sets a variable by name from the current Octave scope.
-	 It is quite fast because the Octave parser is bypassed. 
+	def __getitem__(self, name):
+		if not isinstance(name, basestring):
+			raise TypeError('Expected a string, not a ' + repr(type(name)))
+		try:
+			return _pytave.getvar(name, self.global_variables)
+		except VarNameError:
+			raise KeyError('No Octave variable named ' + name)
 
-	 global specifies that a global variable should be assigned to;
-	 otherwise, local variable (in the current scope) is always
-	 searched for.
-
-	 If the variable is not defined, a new variable is created.
-
-	 If the variable name is not valid, VarNameError exception is raised.
-	 """
-
-	 return _pytave.setvar(name, val, fglobal)
+	def __setitem__(self, name, value):
+		if not isinstance(name, basestring):
+			raise TypeError('Expected a string, not a ' + repr(type(name)))
+		_pytave.setvar(name, value, self.global_variables)
 
-def isvar(name, fglobal = False):
-	 """Checks whether a variable exists in the current Octave scope.
-	 It is quite fast because the Octave parser is bypassed. 
+	def __contains__(self, name):
+		if not isinstance(name, basestring):
+			raise TypeError('Expected a string, not a ' + repr(type(name)))
+		return _pytave.isvar(name, self.global_variables)
 
-	 global specifies that a global variable should be looked up;
-	 otherwise, local variable (in the current scope) is always
-	 searched for.
 
-	 If the variable is defined, returns True, otherwise returns False.
-	 """
-
-	 return _pytave.isvar(name, fglobal)
+locals = _VariablesDict(global_variables=False)
+globals = _VariablesDict(global_variables=True)
 
 def push_scope():
 	 """Creates a new anonymous local variable scope on the Octave call
@@ -210,7 +196,7 @@
 	 """
 	 _pytave.pop_scope()
  
-class _local_scope:
+class _LocalScope:
 	 def __init__(self, func):
 		  self.func = func
 		  self.__name__ = func.__name__
@@ -240,7 +226,7 @@
 		  finally:
 			  pytave.pop_scope()
 	 """
-	 return _local_scope(func)
+	 return _LocalScope(func)
 
 # Emacs
 #	Local Variables:
@@ -248,5 +234,6 @@
 #	coding:utf-8
 #	indent-tabs-mode:t
 #	tab-width:8
+#	python-indent:8
 #	End:
-# vim: set textwidth=70 noexpandtab tabstop=3 :
+# vim: set textwidth=70 noexpandtab tabstop=8 :
--- a/test/test.py	Wed Jun 03 16:41:44 2009 +0200
+++ b/test/test.py	Thu Jun 04 16:20:18 2009 +0200
@@ -3,6 +3,7 @@
 
 import pytave
 import Numeric
+import traceback
 
 print "No messages indicates test pass."
 
@@ -35,48 +36,52 @@
 
 # This eval call is not to be seen as a encouragement to use Pytave
 # like this. Create a separate .m-file with your complex Octave code.
-pytave.feval(0, "eval", "function [result] = test_return(arg) "
-"result = arg; endfunction")
+pytave.eval(0, "function [result] = test_return(arg); result = arg; endfunction")
 
 pytave.feval(1, "test_return", 1)
 
+def fail(msg, exc=None):
+	print "FAIL:", msg
+	traceback.print_stack()
+	if exc is not None:
+		traceback.print_exc(exc)
+	print ""
+
 def testequal(value):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
 		if nvalue != value:
-			print "FAIL as ", value, " != ", nvalue
+			fail("as %s != %s" % (value, nvalue))
 	except TypeError, e:
-		print "FAIL: ", value,":", e
+		fail(value, e)
 
 def testexpect(value, expected):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
 		if nvalue != expected:
-			print "FAIL as ", nvalue, " != ", expected, ","
-			print "        sent in", value
+			fail("sent in %s, expecting %s, got %s", (value, expected, nvalue))
 	except TypeError, e:
-		print "FAIL: ", value,":", e
-
+		fail(value, e)
 
 def testmatrix(value):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
-#		print "test", (value,)
-#		print "returned ", (nvalue,)
 		class1 = pytave.feval(1, "class", value)
 		class2 = pytave.feval(1, "class", nvalue)
 		if nvalue != value:
-			print "FAIL as ", value, " != ", nvalue
+			fail("as %s != %s" % (value, nvalue))
 		if value.shape != nvalue.shape:
-			print "Size check failed for: ", (value,) ,". Got ",value.shape, "and later", nvalue.shape, " =++ ", (nvalue,)
+			fail("Size check failed for: %s. Expected shape %s, got %s  with shape %s" \
+			%(value, value.shape, nvalue.shape, nvalue))
 		if class1 != class2:
-			print "Type check failed for: ", (value,) ,". Got ",class1, "and later", class2
+			fail( "Type check failed for: %s. Expected %s. Got %s."
+			%(value, class1, class2))
 	except TypeError, e:
-		print "Execute failed: ", value,":", e
+		fail("Execute failed: %s" % value, e)
 
 def testobjecterror(value):
 	try:
-		print pytave.feval(1, "test_return", value);
+		pytave.feval(1, "test_return", value);
 		print "FAIL:", (value,)
 	except pytave.ObjectConvertError:
 		pass
@@ -85,16 +90,16 @@
 
 def testvalueerror(*value):
 	try:
-		print pytave.feval(1, *value);
-		print "FAIL:", (value,)
+		pytave.feval(1, *value);
+		fail(value)
 	except pytave.ValueConvertError:
 		pass
 	except Exception, e:
-		print "FAIL", (value,), e
+		fail(value, e)
 
 def testparseerror(*value):
 	try:
-		print pytave.eval(*value);
+		pytave.eval(*value);
 		print "FAIL:", (value,)
 	except pytave.ParseError:
 		pass
@@ -111,41 +116,40 @@
 	try:
 		results = pytave.eval(numargout, code);
 		if results != expectations:
-			print "FAIL: eval: ", code, " because", results, " != ", expectations, ","
+			fail("eval: %s : because %s != %s" % (code, results, expectations))
 	except Exception, e:
-		print "FAIL: eval:", code, ":", e
-def testcellinvariant(value):
-	pass
+		fail("eval: %s" % code, e)
 
-def testsetget(name,value):
-    try:
-	pytave.setvar(name,value)
-	result, = pytave.feval(1, "isequal", value, pytave.getvar(name))
-	if not result:
-	    print "FAIL: set/get: ", name," -> ",value," results diverged"
-    except Exception, e:
-	print "FAIL: set/get: ", name, ":"
+def testsetget(variables, name, value):
+	try:
+		variables[name] = value
+		if name not in variables:
+			print "FAIL: set/get: ", name,": Should exist, not there."
+		result, = pytave.feval(1, "isequal", value, variables[name])
+		if not result:
+			print "FAIL: set/get: ", name," -> ",value," results diverged"
+	except Exception, e:
+		print "FAIL: set/get: ", name, ":", e
 
-def testvarnameerror(name):
-    try:
-	pytave.setvar(name)
-	print "FAIL: ", name
-    except pytave.VarNameError:
-	pass
-    except Exception, e:
-	print "FAIL: ", name
+def testexception(exception, func):
+	try:
+		func()
+		print "FAIL: ", name
+	except Exception, e:
+		if not isinstance(e, exception):
+			print "FAIL:", name, ":", e
 
 def testlocalscope(x):
 
     @pytave.local_scope
     def sloppy_factorial(x):
-	pytave.setvar("x",x)
+	pytave.locals["x"] = x
 	xm1, = pytave.eval(1,"x-1")
 	if xm1 > 0:
 	    fxm1 = sloppy_factorial(xm1)
 	else:
 	    fxm1 = 1
-	pytave.setvar("fxm1",fxm1)
+	pytave.locals["fxm1"] = fxm1
 	fx, = pytave.eval(1,"x * fxm1")
 	return fx
 
@@ -155,9 +159,9 @@
 	for k in range(1,x+1):
 	    fx1 = k * fx1
 	if fx != fx1:
-	    print 'FAIL: testlocalscope: result incorrect'
+	    fail('testlocalscope: result incorrect')
     except Exception, e:
-	print "FAIL: testlocalscope:", (x,), e
+	fail("testlocalscope: %s" % (x,), e)
 
 
 testequal('a')
@@ -271,7 +275,28 @@
 testevalexpect(1, "{2}", ([2],))
 testevalexpect(2, "struct('foo', 2)", ({'foo': [2]},))
 
-testsetget("xxx", [1,2,3])
+testsetget(pytave.locals, "xxx", [1,2,3])
+testsetget(pytave.globals, "xxx", [1,2,3])
+
+def func():
+	pytave.locals["this is not a valid Octave identifier"] = 1
+testexception(pytave.VarNameError, func)
+
+def func():
+	pytave.locals["nonexistentvariable"]
+testexception(KeyError, func)
+
+def func(key):
+	pytave.locals[key] = 1
+testexception(TypeError, lambda: func(0.1))
+testexception(TypeError, lambda: func(1))
+testexception(TypeError, lambda: func([]))
+
+def func(key):
+	pytave.locals[key]
+testexception(TypeError, lambda: func(0.1))
+testexception(TypeError, lambda: func(1))
+testexception(TypeError, lambda: func([]))
 
 testlocalscope(5)
 
@@ -279,3 +304,13 @@
 
 testexpect(arr1o,arr1o[0].tolist())
 testexpect(arr1ch,arr1ch.tostring())
+
+# Emacs
+#	Local Variables:
+#	fill-column:70
+#	coding:utf-8
+#	indent-tabs-mode:t
+#	tab-width:8
+#	python-indent:8
+#	End:
+# vim: set textwidth=70 noexpandtab tabstop=8 :