Commit dfe3dfb7 authored by David Gobbi's avatar David Gobbi Committed by Kitware Robot
Browse files

Merge topic 'python-py3k-tests'

26ad0555 Fix some converted python print statements.
b1f2f2c7 Fix a few simple py3k syntax errors.
8b32c4d3

 Fix numpy_interface compatibility with py3k.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !506
parents 9a1e4654 26ad0555
......@@ -38,7 +38,7 @@ except:
try:
b = vtk.vtkObject()
d = b.SafeDownCast(o)
print(b, d)
print(repr(b) + " " + repr(d))
except:
print("Cannot downcast")
sys.exit(1)
......
......@@ -8,7 +8,7 @@ arrayType = ['Bit', 'Char', 'Double', 'Float', 'Int', 'Long', 'Short',\
'UnsignedChar', 'UnsignedInt', 'UnsignedLong', 'UnsignedShort']
for array in arrayType:
print(array, 'array')
print(array + ' array')
vtkClass = 'vtk' + array + 'Array'
a = getattr(vtk, vtkClass)()
a.Allocate(1,1)
......
......@@ -438,12 +438,12 @@ def BatchTest(vtkClasses, batchNo, batchSize):
def PrintResultSummary():
print('-' * 40)
print('Empty Input worked:', len(emptyInputWorked))
print('Empty Input failed:', len(emptyInputFailed))
print('Abstract classes: ', len(abstractClasses))
print('Non-existent classes: ', len(nonexistentClasses))
print('No concrete implementation: ', len(noConcreteImplementation))
print('No observer could be added: ', len(noObserver))
print('Empty Input worked: %i' % len(emptyInputWorked))
print('Empty Input failed: %i' % len(emptyInputFailed))
print('Abstract classes: %i' % len(abstractClasses))
print('Non-existent classes: %i' % len(nonexistentClasses))
print('No concrete implementation: %i' % len(noConcreteImplementation))
print('No observer could be added: %i' % len(noObserver))
print('-' * 40)
print('Total number of classes tested: ', len(classesTested)) # , classesTested
print('-' * 40)
......
......@@ -14,7 +14,7 @@ from vtk.test import Testing
try:
import numpy
except ImportError:
print("Numpy (http://numpy.scipy.org) not found.",)
print("Numpy (http://numpy.scipy.org) not found.")
print("This test requires numpy!")
sys.exit(0)
......
......@@ -228,7 +228,7 @@ def TestOne(cname):
# Key is not present
setParameterFail[cname] = set(['Set' + m])
except Exception as err:
print(cname, 'Set' + m, err)
print(cname + 'Set' + m + ' ' + str(err))
except TypeError:
# Get...() takes 1 or more arguments.
try:
......@@ -239,7 +239,7 @@ def TestOne(cname):
# Key is not present
getParameterFail[cname] = set(['Get' + m])
except Exception as err:
print(cname, 'Get' + m, err)
print(cname + 'Get' + m + ' ' + str(err))
ok = setGetStatus
else:
noGetSetPairs.add(cname)
......@@ -346,16 +346,16 @@ def BatchTest(vtkClasses, batchNo, batchSize):
def PrintResultSummary():
print('-' * 40)
print('Set(Get()) worked:', len(setGetWorked))
print('Set(Get()) failed:', len(setGetFailed))
print('Abstract classes: ', len(abstractClasses))
print('Non-existent classes: ', len(nonexistentClasses))
print('No concrete implementation: ', len(noConcreteImplementation))
print('No observer could be added: ', len(noObserver))
print('Set(Get()) worked: %i' % len(setGetWorked))
print('Set(Get()) failed: %i' % len(setGetFailed))
print('Abstract classes: %i' % len(abstractClasses))
print('Non-existent classes: %i' % len(nonexistentClasses))
print('No concrete implementation: %i' % len(noConcreteImplementation))
print('No observer could be added: %i' % len(noObserver))
print('-' * 40)
print('Total number of classes tested: ', len(classesTested))
print('Total number of classes tested: %i' % len(classesTested))
print('-' * 40)
print('Excluded from testing: ', len(classExceptions))
print('Excluded from testing: %i' % len(classExceptions))
print('-' * 40)
def ProgramOptions():
......
......@@ -92,8 +92,8 @@ class GtkGLExtVTKRenderWindowInteractor(gtk.gtkgl.DrawingArea):
elif hasattr(self._Iren, attr):
return getattr(self._Iren, attr)
else:
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def CreateTimer(self, obj, event):
gtk.timeout_add(10, self._Iren.TimerEvent)
......
......@@ -95,8 +95,8 @@ class GtkVTKRenderWindowInteractor(gtkgl.GtkGLArea):
elif hasattr(self._Iren, attr):
return getattr(self._Iren, attr)
else:
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def CreateTimer(self, obj, event):
gtk.timeout_add(10, self._Iren.TimerEvent)
......
......@@ -8,6 +8,7 @@ guidelines. For details, see the documentation of individual
algorithms.
"""
from __future__ import absolute_import
import sys
try:
import numpy
......@@ -25,6 +26,11 @@ except ImportError:
vtkMultiProcessController = None
vtkMPI4PyCommunicator = None
if sys.hexversion < 0x03000000:
izip = itertools.izip
else:
izip = zip
def _apply_func2(func, array, args):
"""Apply a function to each member of a VTKCompositeDataArray.
Returns a list of arrays.
......@@ -67,7 +73,7 @@ def apply_dfunc(dfunc, array1, val2):
VTKArray and numpy arrays are also supported."""
if type(array1) == dsa.VTKCompositeDataArray and type(val2) == dsa.VTKCompositeDataArray:
res = []
for a1, a2 in itertools.izip(array1.Arrays, val2.Arrays):
for a1, a2 in izip(array1.Arrays, val2.Arrays):
if a1 is dsa.NoneArray or a2 is dsa.NoneArray:
res.append(dsa.NoneArray)
else:
......@@ -421,7 +427,7 @@ def _global_per_block(impl, array, axis=None, controller=None):
it.GoToNextItem()
# Fill the local array with available values.
for _id, _res in itertools.izip(ids, results):
for _id, _res in izip(ids, results):
success = True
try:
loc = reduce_ids.index(_id)
......@@ -770,13 +776,13 @@ def make_vector(arrayx, arrayy, arrayz=None):
if type(arrayx) == dsa.VTKCompositeDataArray and type(arrayy) == dsa.VTKCompositeDataArray and (type(arrayz) == dsa.VTKCompositeDataArray or arrayz is None):
res = []
if arrayz is None:
for ax, ay in itertools.izip(arrayx.Arrays, arrayy.Arrays):
for ax, ay in izip(arrayx.Arrays, arrayy.Arrays):
if ax is not dsa.NoneArray and ay is not dsa.NoneArray:
res.append(algs.make_vector(ax, ay))
else:
res.append(dsa.NoneArray)
else:
for ax, ay, az in itertools.izip(arrayx.Arrays, arrayy.Arrays, arrayz.Arrays):
for ax, ay, az in izip(arrayx.Arrays, arrayy.Arrays, arrayz.Arrays):
if ax is not dsa.NoneArray and ay is not dsa.NoneArray and az is not dsa.NoneArray:
res.append(algs.make_vector(ax, ay, az))
else:
......
......@@ -73,6 +73,11 @@ from vtk.util import numpy_support
from vtk.vtkCommonDataModel import vtkDataObject
import weakref
if sys.hexversion < 0x03000000:
izip = itertools.izip
else:
izip = zip
def reshape_append_ones (a1, a2):
"""Returns a list with the two arguments, any of them may be
processed. If the arguments are numpy.ndarrays, append 1s to the
......@@ -164,13 +169,17 @@ def _make_tensor_array_contiguous(array):
return array.transpose(0, 2, 1)
return array
class VTKArray(numpy.ndarray):
"""This is a sub-class of numpy ndarray that stores a
reference to a vtk array as well as the owning dataset.
The numpy array and vtk array should point to the same
memory location."""
def __metaclass__(name, parent, attr):
def _metaclass(mcs):
"""For compatibility between python 2 and python 3."""
def decorator(cls):
body = vars(cls).copy()
body.pop('__dict__', None)
body.pop('__weakref__', None)
return mcs(cls.__name__, cls.__bases__, body)
return decorator
class VTKArrayMetaClass(type):
def __new__(mcs, name, parent, attr):
"""We overwrite numerical/comparison operators because we might need
to reshape one of the arrays to perform the operation without
broadcast errors. For instace:
......@@ -219,7 +228,8 @@ class VTKArray(numpy.ndarray):
add_default_numeric_ops("add")
add_default_numeric_ops("sub")
add_default_numeric_ops("mul")
add_default_numeric_ops("div")
if sys.hexversion < 0x03000000:
add_default_numeric_ops("div")
add_default_numeric_ops("truediv")
add_default_numeric_ops("floordiv")
add_default_numeric_ops("mod")
......@@ -236,8 +246,14 @@ class VTKArray(numpy.ndarray):
add_default_numeric_op("ne")
add_default_numeric_op("ge")
add_default_numeric_op("gt")
return type(name, parent, attr)
return type.__new__(mcs, name, parent, attr)
@_metaclass(VTKArrayMetaClass)
class VTKArray(numpy.ndarray):
"""This is a sub-class of numpy ndarray that stores a
reference to a vtk array as well as the owning dataset.
The numpy array and vtk array should point to the same
memory location."""
def _numeric_op(self, other, attr_name):
"""Used to implement numpy-style numerical operations such as __add__,
......@@ -292,19 +308,8 @@ class VTKArray(numpy.ndarray):
raise AttributeError("class has no attribute %s" % name)
return getattr(self.VTKObject, name)
class VTKNoneArray(object):
"""VTKNoneArray is used to represent a "void" array. An instance
of this class (NoneArray) is returned instead of None when an
array that doesn't exist in a DataSetAttributes is requested.
All operations on the NoneArray return NoneArray. The main reason
for this is to support operations in parallel where one of the
processes may be working on an empty dataset. In such cases,
the process is still expected to evaluate a whole expression because
some of the functions may perform bulk MPI communication. None
cannot be used in these instances because it cannot properly override
operators such as __add__, __sub__ etc. This is the main raison
d'etre for VTKNoneArray."""
def __metaclass__(name, parent, attr):
class VTKNoneArrayMetaClass(type):
def __new__(mcs, name, parent, attr):
"""Simplify the implementation of the numeric/logical sequence API."""
def _add_op(attr_name, op):
"""Create an attribute named attr_name that calls
......@@ -330,7 +335,8 @@ class VTKNoneArray(object):
_add_default_ops("add")
_add_default_ops("sub")
_add_default_ops("mul")
_add_default_ops("div")
if sys.hexversion < 0x03000000:
_add_default_ops("div")
_add_default_ops("truediv")
_add_default_ops("floordiv")
_add_default_ops("mod")
......@@ -349,7 +355,21 @@ class VTKNoneArray(object):
_add_default_op("ne")
_add_default_op("ge")
_add_default_op("gt")
return type(name, parent, attr)
return type.__new__(mcs, name, parent, attr)
@_metaclass(VTKNoneArrayMetaClass)
class VTKNoneArray(object):
"""VTKNoneArray is used to represent a "void" array. An instance
of this class (NoneArray) is returned instead of None when an
array that doesn't exist in a DataSetAttributes is requested.
All operations on the NoneArray return NoneArray. The main reason
for this is to support operations in parallel where one of the
processes may be working on an empty dataset. In such cases,
the process is still expected to evaluate a whole expression because
some of the functions may perform bulk MPI communication. None
cannot be used in these instances because it cannot properly override
operators such as __add__, __sub__ etc. This is the main raison
d'etre for VTKNoneArray."""
def __getitem__(self, index):
return NoneArray
......@@ -361,18 +381,8 @@ class VTKNoneArray(object):
NoneArray = VTKNoneArray()
class VTKCompositeDataArray(object):
"""This class manages a set of arrays of the same name contained
within a composite dataset. Its main purpose is to provide a
Numpy-type interface to composite data arrays which are naturally
nothing but a collection of vtkDataArrays. A VTKCompositeDataArray
makes such a collection appear as a single Numpy array and support
all array operations that this module and the associated algorithm
module support. Note that this is not a subclass of a Numpy array
and as such cannot be passed to native Numpy functions. Instead
VTK modules should be used to process composite arrays.
"""
def __metaclass__(name, parent, attr):
class VTKCompositeDataArrayMetaClass(type):
def __new__(mcs, name, parent, attr):
"""Simplify the implementation of the numeric/logical sequence API."""
def add_numeric_op(attr_name, op):
"""Create an attribute named attr_name that calls
......@@ -406,7 +416,8 @@ class VTKCompositeDataArray(object):
add_default_numeric_ops("add")
add_default_numeric_ops("sub")
add_default_numeric_ops("mul")
add_default_numeric_ops("div")
if sys.hexversion < 0x03000000:
add_default_numeric_ops("div")
add_default_numeric_ops("truediv")
add_default_numeric_ops("floordiv")
add_default_numeric_ops("mod")
......@@ -425,7 +436,20 @@ class VTKCompositeDataArray(object):
add_default_numeric_op("ne")
add_default_numeric_op("ge")
add_default_numeric_op("gt")
return type(name, parent, attr)
return type.__new__(mcs, name, parent, attr)
@_metaclass(VTKCompositeDataArrayMetaClass)
class VTKCompositeDataArray(object):
"""This class manages a set of arrays of the same name contained
within a composite dataset. Its main purpose is to provide a
Numpy-type interface to composite data arrays which are naturally
nothing but a collection of vtkDataArrays. A VTKCompositeDataArray
makes such a collection appear as a single Numpy array and support
all array operations that this module and the associated algorithm
module support. Note that this is not a subclass of a Numpy array
and as such cannot be passed to native Numpy functions. Instead
VTK modules should be used to process composite arrays.
"""
def __init__(self, arrays = [], dataset = None, name = None,
association = ArrayAssociation.FIELD):
......@@ -487,7 +511,7 @@ class VTKCompositeDataArray(object):
self.__init_from_composite()
res = []
if type(index) == VTKCompositeDataArray:
for a, idx in itertools.izip(self._Arrays, index.Arrays):
for a, idx in izip(self._Arrays, index.Arrays):
if a is not NoneArray:
res.append(a.__getitem__(idx))
else:
......@@ -506,7 +530,7 @@ class VTKCompositeDataArray(object):
self.__init_from_composite()
res = []
if type(other) == VTKCompositeDataArray:
for a1, a2 in itertools.izip(self._Arrays, other.Arrays):
for a1, a2 in izip(self._Arrays, other.Arrays):
if a1 is not NoneArray and a2 is not NoneArray:
l = reshape_append_ones(a1, a2)
res.append(op(l[0],l[1]))
......@@ -527,7 +551,7 @@ class VTKCompositeDataArray(object):
self.__init_from_composite()
res = []
if type(other) == VTKCompositeDataArray:
for a1, a2 in itertools.izip(self._Arrays, other.Arrays):
for a1, a2 in izip(self._Arrays, other.Arrays):
if a1 is not NoneArray and a2 is notNoneArray:
l = reshape_append_ones(a2,a1)
res.append(op(l[0],l[1]))
......@@ -621,7 +645,9 @@ class DataSetAttributes(VTKObjectWrapper):
if not isinstance(narray, numpy.ndarray) or numpy.ndim(narray) == 0: # Scalar input
narray = narray * numpy.ones(arrLength)
elif narray.shape[0] != arrLength: # Vector input
components = reduce(operator.mul, narray.shape)
components = 1
for l in narray.shape:
components *= l
narray = narray.flatten() * numpy.ones((arrLength, components))
shape = narray.shape
......@@ -712,8 +738,8 @@ class CompositeDataSetAttributes():
# don't add the narray since it's a scalar. GetArray() will create a
# VTKCompositeArray on-demand.
else:
for ds, array in itertools.izip(self.DataSet, narray.Arrays):
if array != None:
for ds, array in izip(self.DataSet, narray.Arrays):
if array is not None:
ds.GetAttributes(self.Association).append(array, name)
added = True
if added:
......@@ -784,7 +810,7 @@ class MultiCompositeDataIterator(CompositeDataIterator):
CompositeDataIterator.__init__(self, cds[0])
self.Datasets = cds
def next(self):
def __next__(self):
if not self.Iterator:
raise StopIteration
......@@ -798,6 +824,9 @@ class MultiCompositeDataIterator(CompositeDataIterator):
self.Iterator.GoToNextItem()
return retVal
def next(self):
return self.__next__()
class DataObject(VTKObjectWrapper):
"""A wrapper for vtkDataObject that makes it easier to access FielData
arrays as VTKArrays
......@@ -905,7 +934,7 @@ class CompositeDataSet(DataObject):
pts.append(NoneArray)
else:
pts.append(_pts)
if len(pts) == 0 or all(map(lambda a : a is NoneArray, pts)):
if len(pts) == 0 or all([a is NoneArray for a in pts]):
cpts = NoneArray
else:
cpts = VTKCompositeDataArray(pts, dataset=self)
......
......@@ -522,7 +522,7 @@ def make_vector(ax, ay, az=None):
if ax is dsa.NoneArray or ay is dsa.NoneArray or ay is dsa.NoneArray:
return dsa.NoneArray
if len(ax.shape) != 1 or len(ay.shape) != 1 or (az != None and len(az.shape) != 1):
if len(ax.shape) != 1 or len(ay.shape) != 1 or (az is not None and len(az.shape) != 1):
raise ValueError("Can only merge 1D arrays")
if az is None:
......
......@@ -208,8 +208,8 @@ class QVTKRenderWindowInteractor(QtGui.QWidget):
elif hasattr(self._Iren, attr):
return getattr(self._Iren, attr)
else:
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def Finalize(self):
'''
......
......@@ -22,7 +22,7 @@ class Tester:
if obj != self.obj:
self.testParse(obj)
methods = self.parser.get_set_methods()
toggle = map(lambda x: x[:-2], self.parser.toggle_methods())
toggle = [x[:-2] for x in self.parser.toggle_methods()]
methods.extend(toggle)
for method in methods:
if method in excluded_methods:
......
......@@ -267,21 +267,21 @@ def _printCDashImageError(img_err, err_index, img_base):
"""Prints the XML data necessary for CDash."""
img_base = _getTempImagePath(img_base)
print("Failed image test with error: %f"%img_err)
print("<DartMeasurement name=\"ImageError\" type=\"numeric/double\">",)
print("%f </DartMeasurement>"%img_err)
print("<DartMeasurement name=\"ImageError\" type=\"numeric/double\"> "
"%f </DartMeasurement>"%img_err)
if err_index <= 0:
print("<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>",)
print("<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>")
else:
print("<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\">",)
print("%d </DartMeasurement>"%err_index)
print("<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\"> "
"%d </DartMeasurement>"%err_index)
print("<DartMeasurementFile name=\"TestImage\" type=\"image/png\">",)
print("%s </DartMeasurementFile>"%(img_base + '.png'))
print("<DartMeasurementFile name=\"TestImage\" type=\"image/png\"> "
"%s </DartMeasurementFile>"%(img_base + '.png'))
print("<DartMeasurementFile name=\"DifferenceImage\" type=\"image/png\">",)
print("%s </DartMeasurementFile>"%(img_base + '.diff.png'))
print("<DartMeasurementFile name=\"ValidImage\" type=\"image/png\">",)
print("%s </DartMeasurementFile>"%(img_base + '.valid.png'))
print("<DartMeasurementFile name=\"DifferenceImage\" type=\"image/png\"> "
"%s </DartMeasurementFile>"%(img_base + '.diff.png'))
print("<DartMeasurementFile name=\"ValidImage\" type=\"image/png\"> "
"%s </DartMeasurementFile>"%(img_base + '.valid.png'))
def _printCDashImageNotFoundError(img_fname):
"""Prints the XML data necessary for Dart when the baseline image is not found."""
......@@ -289,13 +289,13 @@ def _printCDashImageNotFoundError(img_fname):
def _printCDashImageSuccess(img_err, err_index):
"Prints XML data for Dart when image test succeeded."
print("<DartMeasurement name=\"ImageError\" type=\"numeric/double\">",)
print("%f </DartMeasurement>"%img_err)
print("<DartMeasurement name=\"ImageError\" type=\"numeric/double\"> "
"%f </DartMeasurement>"%img_err)
if err_index <= 0:
print("<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>",)
print("<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>")
else:
print("<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\">",)
print("%d </DartMeasurement>"%err_index)
print("<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\"> "
"%d </DartMeasurement>"%err_index)
def _handleFailedImage(idiff, pngr, img_fname):
......@@ -348,10 +348,10 @@ def main(cases):
tot_wall_time = float(time.time() - s_wall_time)
# output measurements for CDash
print("<DartMeasurement name=\"WallTime\" type=\"numeric/double\">",)
print(" %f </DartMeasurement>"%tot_wall_time)
print("<DartMeasurement name=\"CPUTime\" type=\"numeric/double\">",)
print(" %f </DartMeasurement>"%tot_time)
print("<DartMeasurement name=\"WallTime\" type=\"numeric/double\"> "
" %f </DartMeasurement>"%tot_wall_time)
print("<DartMeasurement name=\"CPUTime\" type=\"numeric/double\"> "
" %f </DartMeasurement>"%tot_time)
# Delete these to eliminate debug leaks warnings.
del cases, timer
......
......@@ -79,8 +79,8 @@ class vtkTkImageViewerWidget(Tkinter.Widget):
if attr == '_ImageViewer':
addr = self.tk.call(self._w, 'GetImageViewer')[5:]
return vtk.vtkImageViewer('_%s_vtkImageViewer_p' % addr)
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def GetImageViewer(self):
return self._ImageViewer
......
......@@ -139,8 +139,8 @@ class vtkTkRenderWidget(Tkinter.Widget):
# as an attribute but instead have to get it from the tk-side
if attr == '_RenderWindow':
return self.GetRenderWindow()
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def BindTkRenderWidget(self):
"""
......
......@@ -96,8 +96,8 @@ class vtkTkRenderWindowInteractor(Tkinter.Widget):
elif hasattr(self._Iren, attr):
return getattr(self._Iren, attr)
else:
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has no attribute named " + attr)
def BindEvents(self):
""" Bind all the events. """
......
......@@ -2264,7 +2264,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
def _check_value(self, action, value):
# converted value must be one of the choices (if specified)
if action.choices is not None and value not in action.choices:
tup = value, ', '.join(map(repr, action.choices))
tup = value, ', '.join([repr(x) for x in action.choices])
msg = _('invalid choice: %r (choose from %s)') % tup
raise ArgumentError(action, msg)
......
......@@ -38,17 +38,6 @@ import math, os, sys
import wx
import vtk
# wxPython 2.4.0.4 and newer prefers the use of True and False, standard
# booleans in Python 2.2 but not earlier. Here we define these values if
# they don't exist so that we can use True and False in the rest of the
# code. At the time of this writing, that happens exactly ONCE in
# CreateTimer()
try:
True
except NameError:
True = 1
False = 0
# a few configuration items, see what works best on your system
# Use GLCanvas as base class instead of wx.Window.
......@@ -278,8 +267,8 @@ class wxVTKRenderWindowInteractor(baseClass):
elif hasattr(self._Iren, attr):
return getattr(self._Iren, attr)
else:
raise AttributeError, self.__class__.__name__ + \
" has no attribute named " + attr
raise AttributeError(self.__class__.__name__ +
" has