# HG changeset patch # User Jaroslav Hajek # Date 1244455100 -7200 # Node ID 732b6b4b2c45638f0dcfe4dc1908dd6f3790b04e # Parent 43a413b7c151f0f9a392a02b53fd4c39dff70d91 implement dict interface to variables diff -r 43a413b7c151 -r 732b6b4b2c45 ChangeLog --- a/ChangeLog Mon Jun 08 11:55:19 2009 +0200 +++ b/ChangeLog Mon Jun 08 11:58:20 2009 +0200 @@ -15,6 +15,7 @@ (locals, globals): Default instances. (_local_scope): Rename to _LocalScope * test/test.py: New tests. Update old tests. + (testsetget, testexception): New functions. 2009-06-03 Jaroslav Hajek diff -r 43a413b7c151 -r 732b6b4b2c45 package/pytave.py --- a/package/pytave.py Mon Jun 08 11:55:19 2009 +0200 +++ b/package/pytave.py Mon Jun 08 11:58:20 2009 +0200 @@ -157,46 +157,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, native=False): + self.global_variables = global_variables + self.native = native - 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 diff -r 43a413b7c151 -r 732b6b4b2c45 test/test.py --- a/test/test.py Mon Jun 08 11:55:19 2009 +0200 +++ b/test/test.py Mon Jun 08 11:58:20 2009 +0200 @@ -120,32 +120,30 @@ except Exception, e: 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 - fail("eval: %s : because %s != %s" % (code, results, expectations)) +def testexception(exception, func): + try: + func() + print "FAIL: ", name except Exception, e: - fail("eval: %s" % code, 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) @@ -256,6 +254,29 @@ testevalexpect(1, "{2}", ([2],)) testevalexpect(2, "struct('foo', 2)", ({'foo': 2},)) +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) # Emacs