# HG changeset patch # User Mike Miller # Date 1491243953 25200 # Node ID 1af3687133792db86fc3a1d8ea55266b4d7fcf28 # Parent 668fcb0f68ef6361156f8a4836cb8b73a5ba0179 Delete Python support files from legacy pytave project * Makefile.am (PY_FILES): Delete. (EXTRA_DIST): Remove $(PY_FILES). (all-local): Remove comment about using the pytave Python module. diff -r 668fcb0f68ef -r 1af368713379 Makefile.am --- a/Makefile.am Mon Apr 03 08:30:20 2017 -0700 +++ b/Makefile.am Mon Apr 03 11:25:53 2017 -0700 @@ -73,15 +73,9 @@ octave_to_python.h \ python_to_octave.h -PY_FILES = \ - package/__init__.py \ - package/pytave.py \ - test/exceptions.py \ - test/test.py - TST_FILES = $(addsuffix -tst,$(OCT_SOURCE_FILES)) -EXTRA_DIST = $(DOC_FILES) $(OCT_SOURCE_FILES) $(PY_FILES) +EXTRA_DIST = $(DOC_FILES) $(OCT_SOURCE_FILES) EXTRA_libdir = $(PYTAVE_MODULE_INSTALL_PATH) EXTRA_lib_LTLIBRARIES = _pytave.la @@ -148,9 +142,6 @@ @echo " * run an Octave session with py* functions" @echo " octave --path=\"\$$(pwd)\"" @echo "" - @echo " * run a Python session with pytave package" - @echo " PYTHONPATH=\"\$$(pwd)/.libs:\$$(pwd)/package\" python" - @echo "" check-local: $(M_FILES) $(TST_FILES) $(OCTAVE) --no-gui-libs --no-history --no-window-system --norc \ diff -r 668fcb0f68ef -r 1af368713379 package/__init__.py --- a/package/__init__.py Mon Apr 03 08:30:20 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# -*- coding:utf-8 -*- -# -# Copyright (C) 2015-2016 Mike Miller -# Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson -# -# This file is part of Pytave. -# -# Pytave is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# Pytave is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License -# along with Pytave; see the file COPYING. If not, see -# . - -import _pytave -from pytave import * diff -r 668fcb0f68ef -r 1af368713379 package/pytave.py --- a/package/pytave.py Mon Apr 03 08:30:20 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +0,0 @@ -# -*- coding:utf-8 -*- -# -# Copyright (C) 2015-2016 Mike Miller -# Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson -# Copyright (C) 2009 Jaroslav Hajek, VZLU Prague -# -# This file is part of Pytave. -# -# Pytave is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# Pytave is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License -# along with Pytave; see the file COPYING. If not, see -# . - -"""Python to Octave bridge""" - -import _pytave -import atexit -import numpy -import sys - -try: - from collections.abc import MutableMapping -except: - from UserDict import DictMixin as MutableMapping - -arg0 = sys.argv[0] -# Some web application packages, such as mod_wsgi for Apache, -# completely restrict access to stdin, including an isatty() query. -# Hence, if an error occurs, we'll stay safe. -try: - interactive = sys.stdin.isatty() and (arg0 == '' or arg0 == '-') -except IOError: - interactive = False - -_pytave.init(interactive) -(OctaveError, ValueConvertError, ObjectConvertError, ParseError, - VarNameError) = _pytave.get_exceptions() - - -def _atexit(): - _pytave.atexit() - -atexit.register(_atexit) - - -def feval(nargout, funcname, *arguments): - - """Executes an Octave function called funcname. - - The function is set to return nargout values. Returned values - are stored in a tuple. If the nargout argument is less than 0, - an empty tuple is returned. - - M-files are searched for in the Octave path. - - See also the Octave documentation for the builtin Octave function - feval. - - Type conversions - **************** - - The following type conversions are supported: - - Python to Octave - ================ - - Objects: - int (32-bit) int32 - float (64-bit) double - str character array - dict struct - list cell array - - NumPy Array: - UBYTE, SBYTE, matrix of correct type - USHORT, SHORT, -''- - UINT, SINT, -''- - LONG, -''- - DOUBLE -''- - CHAR character array - OBJECT cell array - - All other objects causes a pytave.ObjectConvertError to be - raised. This exception inherits TypeError. - - When dicts are converted, all keys must be strings and - constitute valid Octave identifiers. The behavior is - analogical to the Octave "struct" function: values that - evaluate to cells must have matching dimensions, singleton - cells and non-cell values are expanded. - - Octave to Python - ================ - - All scalar values are regarded as 1x1 matrices, as they are in - Octave. - - Matrix values to NumPy arrays: - double DOUBLE - single FLOAT - logical DOUBLE - int64 LONG - int32, uint32 INT, UINT - int16, uint16 SHORT, USHORT - int8, unint8 SBYTE, UBYTE - char CHAR - cell OBJECT - - Structs are converted to dicts, where each value is an OBJECT - array. - - All other values causes a pytave.ValueConvertError to be - raised. This exception inherits TypeError. - - Errors - ****** - - Octave runtime errors are encapsulated into - pytave.OctaveError exceptions, base class RuntimeError. - - """ - - return _pytave.feval(nargout, funcname, arguments) - - -def eval(nargout, code, silent=True): - - """Executes a given Octave code. - - The expression is expected to return nargout values. Returned - values are stored in a tuple. If the nargout argument is less - than 0, an empty tuple is returned. - - All normal scope and function search rules apply. If silent is - true (default), the result is not auto-printed, as if a - semicolon was appended. Otherwise, auto-printing is enabled. - - See also the Octave documentation for the builtin Octave - function eval. - - For information about returned value conversion, see - pytave.feval. - - Errors - ****** - - If the code cannot be parsed, a pytave.ParseError exception - occurs. - - Octave runtime errors are encapsulated into pytave.OctaveError - exceptions, base class RuntimeError. - - If the resulting values cannot be converted, a - pytave.ValueConvertError is raised. This exception inherits - TypeError. - - """ - - return _pytave.eval(nargout, code, silent) - - -def stripdict(dictarray): - """A helper function to convert structures obtained from Octave. - Because in Octave, all structs are also arrays, they are returned - as dicts of object arrays. In the common case of a 1x1 struct, - stripdict strips the values.""" - - sdict = {} - for key in dictarray: - sdict[key] = dictarray[key][0, 0] - return sdict - - -def narrowlist(objarray): - """A helper function to convert cell arrays obtained from Octave. - Octave cells are returned as NumPy object arrays. This function - will flatten the array and convert it into a 1D list.""" - - return numpy.ravel(objarray).tolist() - - -def simplify(obj): - """A helper function to convert results obtained from Octave. - This will convert all 1x1 arrays to scalars, vectors to 1D arrays, - 1xN and 0x0 character arrays to strings, 1xN, Nx1 and 0x0 cell - arrays to lists, and strip scalar dicts. It will work recursively.""" - - def vectordims(dims, column_allowed=True): - return (len(dims) == 2 and - ((dims[0] == 1 or (column_allowed and dims[1] == 1)) or - (dims[0] == 0 and dims[1] == 0))) - - if isinstance(obj, numpy.ndarray): - tc = obj.dtype.char - if tc == 'O': - if vectordims(numpy.shape(obj)): - return map(simplify, narrowlist(obj)) - elif tc == 'c': - if vectordims(numpy.shape(obj), False): - return obj.tostring() - else: - dims = numpy.shape(obj) - if dims == (1, 1): - return obj[0, 0] - elif vectordims(dims): - return numpy.ravel(obj) - elif isinstance(obj, dict): - sobj = {} - for key in obj: - sval = simplify(obj[key]) - if isinstance(sval, list) and len(sval) == 1: - sval = sval[0] - sobj[key] = sval - return sobj - elif isinstance(obj, tuple): - return tuple(map(simplify, obj)) - return obj - - -def addpath(*arguments): - """See Octave documentation""" - return _pytave.feval(1, "addpath", arguments)[0] - - -def rmpath(*paths): - """See Octave documentation""" - return _pytave.feval(1, "rmpath", paths)[0] - - -def path(*paths): - """See Octave documentation""" - return _pytave.feval(1, "path", paths)[0] - - -def load_package(pkg_name): - """Equivalent to pkg load. See Octave documentation.""" - return _pytave.feval(0, "pkg", ("load", pkg_name)) - - -def unload_package(pkg_name): - """Equivalent to pkg unload. See Octave documentation.""" - return _pytave.feval(0, "pkg", ("unload", pkg_name)) - - -class _VariablesDict(MutableMapping): - def __init__(self, global_variables, native=False): - self.global_variables = global_variables - self.native = native - - 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) - - 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 __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) - - def __delitem__(self, name): - if not isinstance(name, basestring): - raise TypeError('Expected a string, not a ' + repr(type(name))) - # Octave does not gripe when clearing non-existent - # variables. To be consistent with Python dict - # behavior, we shall do so. - if self.__contains__(name): - _pytave.delvar(name, self.global_variables) - else: - raise KeyError('No Octave variable named ' + name) - - -locals = _VariablesDict(global_variables=False) -globals = _VariablesDict(global_variables=True) - - -def push_scope(): - """Creates a new anonymous local variable scope on the Octave call - stack and sets it as the current Octave scope. Subsequent eval, - getvar and setvar calls will affect variables within this scope. - - This is useful to do if you call the Octave engine from within - multiple Python functions, to prevent them from hampering each - other's data. As such, it is advisable to always create a local - scope in a production code. - """ - return _pytave.push_scope() - - -def pop_scope(): - """Pops the current active scope (created previously by - push_scope) off the Octave call stack. The previous scope - will become the active scope. - - If already at the top-level scope, this function does nothing. - """ - _pytave.pop_scope() - - -class _LocalScope: - def __init__(self, func): - self.func = func - self.__name__ = func.__name__ - self.__doc__ = func.__doc__ - - def __call__(self, *args, **kwargs): - try: - _pytave.push_scope() - return self.func(*args, **kwargs) - finally: - _pytave.pop_scope() - - -def local_scope(func): - """Decorates a function to use local Octave scope. - Example: - - @pytave.local_scope - def myfunc(a, b): - - - is equivalent to: - - def myfunc(a, b): - try: - pytave.push_scope() - - finally: - pytave.pop_scope() - """ - return _LocalScope(func) diff -r 668fcb0f68ef -r 1af368713379 test/exceptions.py --- a/test/exceptions.py Mon Apr 03 08:30:20 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- -# -# Copyright (C) 2015-2016 Mike Miller -# Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson -# Copyright (C) 2009 Jaroslav Hajek, VZLU Prague -# -# This file is part of Pytave. -# -# Pytave is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# Pytave is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License -# along with Pytave; see the file COPYING. If not, see -# . - -import pytave - -try: - pytave.feval(1, "") -except pytave.OctaveError as e: - print("test ok") -except: - print("test fail") - -try: - pytave.feval(1, "cell") -except pytave.ValueConvertError as e: - print("test ok") -except: - print("test fail") - -try: - pytave.feval(1, "sin", {"asdf": "asdf"}) -except pytave.ObjectConvertError as e: - print("test ok") -except: - print("test fail") diff -r 668fcb0f68ef -r 1af368713379 test/test.py --- a/test/test.py Mon Apr 03 08:30:20 2017 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,364 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- -# -# Copyright (C) 2015-2016 Mike Miller -# Copyright (C) 2008 David Grundberg, Håkan Fors Nilsson -# Copyright (C) 2009 Jaroslav Hajek, VZLU Prague -# -# This file is part of Pytave. -# -# Pytave is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# Pytave is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License -# along with Pytave; see the file COPYING. If not, see -# . - - -import numpy -import pytave -import traceback - -print("No messages indicates test pass.") - -arr0_0 = numpy.zeros((0, 0)) -arr0_1 = numpy.zeros((0, 1)) -arr1_0 = numpy.zeros((1, 0)) -number = numpy.array([[1.32]], numpy.float32) -arr1fT = numpy.array([[1.32], [2], [3], [4]], numpy.float32) -arr1fT2 = numpy.array([[1.32, 2, 3, 4]], numpy.float32) -arr1f = numpy.array([[1.32, 2, 3, 4]], numpy.float32) -arr1b = numpy.array([[8, 2, 3, 256]], numpy.int8) -arr1i = numpy.array([[17, 2, 3, 4]], numpy.int) -arr1i32 = numpy.array([[32, 2, 3, 4]], numpy.int32) -arr1i64 = numpy.array([[32, 2, 3, 4]], numpy.int64) -arr1a = numpy.array([[1, 2, 3, 4]]) -arr2f = numpy.array([[1.32, 2, 3, 4], [5, 6, 7, 8]], numpy.float32) -arr2d = numpy.array([[1.17, 2, 3, 4], [5, 6, 7, 8]], numpy.float) -arr3f = numpy.array([[[1.32, 2, 3, 4], [5, 6, 7, 8]], - [[9, 10, 11, 12], [13, 14, 15, 16]]], numpy.float32) -arr1c = numpy.array([[1 + 2j, 3 + 4j, 5 + 6j, 7 + 0.5j]], numpy.complex) -arr1fc = numpy.array([[1 + 2j, 3 + 4j, 5 + 6j, 7 + 0.5j]], numpy.complex64) -arr1ch = numpy.array([["abc"]], numpy.character) -arr2ch = numpy.array([["abc"], ["def"]], numpy.character) -arr1o = numpy.array([[1.0, "abc", 2 + 3j]], numpy.object) -arr2o = numpy.array([[1.0, "abc", 2 + 3j], [4.0, arr1i, "def"]], numpy.object) - -alimit_int64 = numpy.array([[-9223372036854775808, 9223372036854775807]], - numpy.int64) -alimit_int32 = numpy.array([[-2147483648, 2147483647]], numpy.int32) -alimit_int16 = numpy.array([[-32768, 32767, -32769, 32768]], numpy.int16) -alimit_int8 = numpy.array([[-128, 127, -129, 128]], numpy.int8) -alimit_uint8 = numpy.array([[0, 255, -1, 256]], numpy.uint8) - - -# Define a function in the Octave test session that simply returns the -# single value given to it. -pytave.eval(0, "function y = test_return (x); y = x; endfunction") - -pytave.feval(1, "test_return", 1) - - -def equals(a, b): - return numpy.alltrue(numpy.ravel(a == b)) - - -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 not equals(value, nvalue): - fail("as %s != %s" % (value, nvalue)) - except Exception as e: - fail(value, e) - - -def testexpect(value, expected): - try: - nvalue, = pytave.feval(1, "test_return", value) - if not equals(value, nvalue): - fail("sent in %s, expecting %s, got %s", (value, expected, nvalue)) - except Exception as e: - fail(value, e) - - -def testmatrix(value): - try: - nvalue, = pytave.feval(1, "test_return", value) - class1, = pytave.feval(1, "class", value) - class1 = class1.tostring() - class2, = pytave.feval(1, "class", nvalue) - class2 = class2.tostring() - if not equals(value, nvalue): - fail("as %s != %s" % (value, nvalue)) - if value.shape != nvalue.shape: - fail("Size check failed for: %s. Expected shape %s, got %s with shape %s" - % (value, value.shape, nvalue, nvalue.shape)) - if class1 != class2: - fail("Type check failed for: %s. Expected %s. Got %s." - % (value, class1, class2)) - except Exception as e: - fail("Execute failed: %s" % value, e) - - -def testobjecterror(value): - try: - pytave.feval(1, "test_return", value) - print("FAIL:", (value,)) - except pytave.ObjectConvertError: - pass - except Exception as e: - print("FAIL", (value,), e) - - -def testvalueerror(*value): - try: - pytave.feval(1, *value) - fail(value) - except pytave.ValueConvertError: - pass - except Exception as e: - fail(value, e) - - -def testparseerror(*value): - try: - pytave.eval(*value) - print("FAIL:", (value,)) - except pytave.ParseError: - pass - except Exception as e: - print("FAIL", (value,), e) - - -def testvalueok(*value): - try: - pytave.feval(1, *value) - except Exception as e: - print("FAIL", (value,), e) - - -def testevalexpect(numargout, code, expectations): - try: - results = pytave.eval(numargout, code) - if not equals(results, expectations): - fail("eval: %s : because %s != %s" % (code, results, expectations)) - except Exception as e: - fail("eval: %s" % code, e) - - -def testsetget(variables, name, value): - try: - variables[name] = value - if name not in variables: - fail("set/get: %s: Should exist, not there." % name) - result, = pytave.feval(1, "isequal", value, variables[name]) - if not result: - fail("set/get: %s -> %s: results diverged" % (name, value)) - except Exception as e: - fail("set/get: %s" % name, e) - - -def testexception(exception, func): - try: - func() - fail("Expecting %s but nothing was raised." % repr(exception)) - except Exception as e: - if not isinstance(e, exception): - fail("Expecting %s but got %s instead" % (repr(exception), repr(e)), e) - - -def testlocalscope(x): - - @pytave.local_scope - def sloppy_factorial(x): - pytave.locals["x"] = x - xm1, = pytave.eval(1, "x - 1") - xm1 = xm1[0][0] - if xm1 > 0: - fxm1 = sloppy_factorial(xm1) - else: - fxm1 = 1 - pytave.locals["fxm1"] = fxm1 - fx, = pytave.eval(1, "x * fxm1") - fx = fx[0][0] - return fx - - try: - fx = sloppy_factorial(x) - fx1 = 1.0 - for k in range(1, x + 1): - fx1 = k * fx1 - if fx != fx1: - fail("testlocalscope: result incorrect") - except Exception as e: - fail("testlocalscope: %s" % (x,), e) - - -def objarray(obj): - return numpy.array(obj, numpy.object) - - -def charray(obj): - return numpy.array(obj, numpy.character) - - -testmatrix(alimit_int64) -testmatrix(alimit_int32) -testmatrix(alimit_int16) -testmatrix(alimit_int8) - -# Strings - -# FIXME: These tests are not working. -# testequal(["mystring"]) -# testequal(["mystringåäöÅÄÖ"]) - -testexpect(1, numpy.array([[1]], numpy.int)) -testexpect(1.0, numpy.array([[1]], numpy.float)) - -# Vector arrays -testmatrix(arr1a) -testmatrix(arr1f) -testmatrix(arr1fT) -testmatrix(arr1fT2) -testmatrix(arr1i) -testmatrix(arr1b) -testmatrix(arr1fc) - -# 2d arrays -testmatrix(arr2f) -testmatrix(arr2d) -testmatrix(arr2ch) - -# 3d arrays -testmatrix(arr3f) - -# Note, both arr0_0 == arr0_0 and arr0_0 != arr0_0 are false! -if (arr0_0 != arr0_0) or (arr0_0 == arr0_0): - print("FAIL: Zero test") - -testmatrix(arr0_0) -testmatrix(arr0_1) -testmatrix(arr1_0) - -# Lists -testexpect([1, 2], objarray([[1, 2]])) -testexpect([], objarray([[]])) - -# Return cells with OK dimensions -testvalueok("cell", 1, 3) -testvalueok("cell", 1, 0) -testvalueok("cell", 0, 0) -testvalueok("cell", 3, 1) -testvalueok("cell", 0, 1) - -# Dictionaries - - -# Simple dictionary tests -testexpect({"foo": 1, "bar": 2}, - {"foo": objarray([[1]]), "bar": objarray([[2]])}) -# testexpect({"x": [1, 3], "y": [2, 4]}, -# {"x": objarray([[1, 3]]), "y": objarray([[2, 4]])}) -# just constructing the second value with Numeric 24.2! -# testexpect({"x": [1, "baz"], "y": [2, "foobar"]}, -# {"x": objarray([[1, charray(["baz"])]]), -# "y": objarray([[2, charray(["foobar"])]])}) - -testequal({"x": objarray([[arr1f]]), "y": objarray([[arr1i]])}) -testequal({}) -testequal({"foo": arr2o, "bar": arr2o}) - -# Try some invalid keys -testobjecterror({"this is not an Octave identifier": 1}) -testobjecterror({1.22: 1}) - -# These should fail: No object conversion defined. -testobjecterror(None) -testobjecterror((1,)) -testobjecterror(()) - -result, = pytave.feval(1, "eval", "[1, 1, 1]") -if result.shape != (1, 3): - print("FAIL: expected length-3 vector") - -result, = pytave.feval(1, "eval", "[1; 2; 3]") -if result.shape != (3, 1): - print("FAIL: expected 3x1 matrix") - -testparseerror(1, "endfunction") -testevalexpect(1, "2 + 2", (4,)) -testevalexpect(1, "{2}", (objarray([[2]]),)) -testevalexpect(1, "struct('foo', 2)", ({"foo": objarray([[2]])},)) - -testsetget(pytave.locals, "xxx", arr1f) -testsetget(pytave.globals, "xxx", arr2o) - - -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) - -testexception(KeyError, lambda: pytave.locals["localvariable"]) -pytave.locals["localvariable"] = 1 -if "localvariable" in pytave.globals: - fail("Local variable in globals") -del pytave.locals["localvariable"] -if "localvariable" in pytave.locals: - fail("Could not clear local variable") -testexception(KeyError, lambda: pytave.locals["localvariable"]) - - -def func(): - del pytave.locals["localvariable"] -testexception(KeyError, lambda: func()) - -testexception(KeyError, lambda: pytave.globals["globalvariable"]) -pytave.globals["globalvariable"] = 1 -if "globalvariable" in pytave.locals: - fail("Global variable in locals") -del pytave.globals["globalvariable"] -if "globalvariable" in pytave.globals: - fail("Could not clear global variable") -testexception(KeyError, lambda: pytave.globals["globalvariable"]) - - -def func(): - del pytave.globals["globalvariable"] -testexception(KeyError, lambda: func())