"""
Test module for enumerated types under PyTables
===============================================
:Author: Ivan Vilata i Balaguer
:Contact: ivan@selidor.net
:Created: 2005-05-09
:License: BSD
:Revision: $Id: test_enum.py 3698 2008-09-09 12:54:51Z faltet $
"""
import unittest
import operator
import numpy
import tables
from tables.tests import common
class CreateColTestCase(common.PyTablesTestCase):
"""Test creating enumerated column descriptions."""
def _createCol(self, enum, dflt, base='uint32', shape=()):
"""Create and check an enumerated column description."""
enumcol = tables.EnumCol(enum, dflt, base=base, shape=shape)
sameEnum = tables.Enum(enum)
self.assertEqual(enumcol.type, 'enum')
self.assertEqual(enumcol.dtype.base.name, enumcol.base.type)
# To avoid 'LongInt' vs 'Int' issues
#self.assertEqual(enumcol.dflt, sameEnum[dflt])
self.assertEqual(int(enumcol.dflt), int(sameEnum[dflt]))
self.assertEqual(enumcol.dtype.shape, shape)
self.assertEqual(enumcol.enum, sameEnum)
def test00a_validFromEnum(self):
"""Describing an enumerated column from an enumeration."""
colors = tables.Enum(['red', 'green', 'blue'])
self._createCol(colors, 'red')
def test00b_validFromDict(self):
"""Describing an enumerated column from a dictionary."""
colors = {'red': 4, 'green': 2, 'blue': 1}
self._createCol(colors, 'red')
def test00c_validFromList(self):
"""Describing an enumerated column from a list."""
colors = ['red', 'green', 'blue']
self._createCol(colors, 'red')
def test00d_invalidFromType(self):
"""Describing an enumerated column from an invalid object."""
colors = 123
self.assertRaises(TypeError, self._createCol, colors, 'red')
def test01_invalidDflt(self):
"""Describing an enumerated column with an invalid default object."""
colors = {'red': 4, 'green': 2, 'blue': 1}
self.assertRaises(KeyError, self._createCol, colors, 'black')
def test02a_validDtypeBroader(self):
"""Describing an enumerated column with a broader type."""
colors = {'red': 4, 'green': 2, 'blue': 1}
self._createCol(colors, 'red', 'int64')
def test02b_invalidDtypeTooNarrow(self):
"""Describing an enumerated column with a too narrow type."""
colors = ['e%d' % i for i in range(300)]
self.assertRaises(TypeError, self._createCol, colors, 'e0', 'uint8')
def test03a_validShapeMD(self):
"""Describing an enumerated column with multidimensional shape."""
colors = ['red', 'green', 'blue']
self._createCol(colors, 'red', shape=(2,))
def test04a_validReprEnum(self):
"""Checking the string representation of an enumeration."""
colors = tables.Enum(['red', 'green', 'blue'])
enumcol = tables.EnumCol(colors, 'red', base='uint32', shape=())
assert repr(enumcol) == \
"""EnumCol(enum=Enum({'blue': 2, 'green': 1, 'red': 0}), dflt='red', base=UInt32Atom(shape=(), dflt=0), shape=(), pos=None)"""
def test99a_nonIntEnum(self):
"""Describing an enumerated column of floats (not implemented)."""
colors = {'red': 1.0}
self.assertRaises(NotImplementedError, self._createCol, colors, 'red',
base=tables.FloatAtom())
def test99b_nonIntDtype(self):
"""Describing an enumerated column encoded as floats (not implemented)."""
colors = ['red', 'green', 'blue']
self.assertRaises(
NotImplementedError, self._createCol, colors, 'red', 'float64')
def test99b_nonScalarEnum(self):
"""Describing an enumerated column of non-scalars (not implemented)."""
colors = {'red': (1, 2, 3)}
self.assertRaises(NotImplementedError, self._createCol, colors, 'red',
base=tables.IntAtom(shape=3))
class CreateAtomTestCase(common.PyTablesTestCase):
"""Test creating enumerated atoms."""
def _createAtom(self, enum, dflt, base='uint32', shape=()):
"""Create and check an enumerated atom."""
enumatom = tables.EnumAtom(enum, dflt, base=base, shape=shape)
sameEnum = tables.Enum(enum)
self.assertEqual(enumatom.type, 'enum')
self.assertEqual(enumatom.dtype.base.name, enumatom.base.type)
self.assertEqual(enumatom.shape, shape)
self.assertEqual(enumatom.enum, sameEnum)
def test00a_validFromEnum(self):
"""Describing an enumerated atom from an enumeration."""
colors = tables.Enum(['red', 'green', 'blue'])
self._createAtom(colors, 'red')
def test00b_validFromDict(self):
"""Describing an enumerated atom from a dictionary."""
colors = {'red': 4, 'green': 2, 'blue': 1}
self._createAtom(colors, 'red')
def test00c_validFromList(self):
"""Describing an enumerated atom from a list."""
colors = ['red', 'green', 'blue']
self._createAtom(colors, 'red')
def test00d_invalidFromType(self):
"""Describing an enumerated atom from an invalid object."""
colors = 123
self.assertRaises(TypeError, self._createAtom, colors, 'red')
def test02a_validDtypeBroader(self):
"""Describing an enumerated atom with a broader type."""
colors = {'red': 4, 'green': 2, 'blue': 1}
self._createAtom(colors, 'red', base='int64')
def test02b_invalidDtypeTooNarrow(self):
"""Describing an enumerated atom with a too narrow type."""
colors = ['e%d' % i for i in range(300)]
self.assertRaises(TypeError, self._createAtom, colors, 'red', 'uint8')
def test03a_validShapeMD(self):
"""Describing an enumerated atom with multidimensional shape."""
colors = ['red', 'green', 'blue']
self._createAtom(colors, 'red', shape=(2,))
def test99a_nonIntEnum(self):
"""Describing an enumerated atom of floats (not implemented)."""
colors = {'red': 1.0}
self.assertRaises(NotImplementedError, self._createAtom, colors, 'red',
base=tables.FloatAtom())
def test99b_nonIntDtype(self):
"""Describing an enumerated atom encoded as a float (not implemented)."""
colors = ['red', 'green', 'blue']
self.assertRaises(
NotImplementedError, self._createAtom, colors, 'red', 'float64')
def test99b_nonScalarEnum(self):
"""Describing an enumerated atom of non-scalars (not implemented)."""
colors = {'red': (1, 2, 3)}
self.assertRaises(NotImplementedError, self._createAtom, colors, 'red',
base=tables.IntAtom(shape=3))
class EnumTableTestCase(common.TempFileMixin, common.PyTablesTestCase):
"""Test tables with enumerated columns."""
enum = tables.Enum({'red': 4, 'green': 2, 'blue': 1, 'black': 0})
defaultName = 'black'
valueInEnum = enum.red
valueOutOfEnum = 1234
enumType = 'uint16'
def _description(self, shape=()):
class TestDescription(tables.IsDescription):
rid = tables.IntCol(pos=0)
rcolor = tables.EnumCol(
self.enum, self.defaultName,
base=self.enumType, shape=shape, pos=1)
return TestDescription
def test00a_reopen(self):
"""Reopening a file with tables using enumerated data."""
self.h5file.createTable(
'/', 'test', self._description(), title=self._getMethodName())
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum('rcolor'), self.enum,
"Enumerated type was not restored correctly from disk.")
def test00b_reopenMD(self):
"""
Reopening a file with tables using enumerated multi-dimensional
data.
"""
self.h5file.createTable(
'/', 'test', self._description((2,)), title=self._getMethodName())
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum('rcolor'), self.enum,
"Enumerated type was not restored correctly from disk.")
def test01_rowAppend(self):
"""Appending enumerated values using ``row.append()``."""
tbl = self.h5file.createTable(
'/', 'test', self._description(), title=self._getMethodName())
appended = [
(10, self.valueInEnum),
(20, self.valueOutOfEnum)]
row = tbl.row
row['rid'] = appended[0][0]
row['rcolor'] = appended[0][1]
row.append()
row['rid'] = appended[1][0]
self.assertRaises(
ValueError, operator.setitem, row, 'rcolor', appended[1][1])
tbl.flush()
tbl.flavor = 'python'
read = tbl.read()
common.verbosePrint(
"* appended value: %s\n"
"* read value: %s\n"
% (appended[:-1], read) )
self.assertEqual(
appended[:-1], read, "Written and read values differ.")
def test02_append(self):
"""Appending enumerated values using ``table.append()``."""
tbl = self.h5file.createTable(
'/', 'test', self._description(), title=self._getMethodName())
appended = [
(10, self.valueInEnum),
(20, self.valueOutOfEnum)]
tbl.append(appended)
tbl.flush()
tbl.flavor = 'python'
read = tbl.read()
common.verbosePrint(
"* appended value: %s\n"
"* read value: %s\n"
% (appended, read) )
self.assertEqual(appended, read, "Written and read values differ.")
def test03_setitem(self):
"""Changing enumerated values using ``table.__setitem__()``."""
tbl = self.h5file.createTable(
'/', 'test', self._description(), title=self._getMethodName())
appended = [
(10, self.valueInEnum),
(20, self.valueInEnum)]
tbl.append(appended)
written = [
(10, self.valueInEnum),
(20, self.valueOutOfEnum)]
tbl[:] = written
tbl.flavor = 'python'
read = tbl.read()
common.verbosePrint(
"* written value: %s\n"
"* read value: %s\n"
% (written, read) )
self.assertEqual(written, read, "Written and read values differ.")
def test04_multidim(self):
"""Appending multi-dimensional enumerated data."""
tbl = self.h5file.createTable(
'/', 'test', self._description((2,)), title=self._getMethodName())
appended = [
(10, (self.valueInEnum, self.valueOutOfEnum)),
(20, (self.valueInEnum, self.valueOutOfEnum))]
row = tbl.row
row['rid'] = appended[0][0]
self.assertRaises(
ValueError, operator.setitem, row, 'rcolor', appended[0][1])
tbl.append(appended)
tbl.flush()
tbl.flavor = 'python'
read = tbl.read()
for i in range(len(appended)):
self.assertEqual(appended[i][0], read[i][0],
"Written and read values differ.")
self.assertEqual(appended[i][1][0], read[i][1][0],
"Written and read values differ.")
self.assertEqual(appended[i][1][1], read[i][1][1],
"Written and read values differ.")
def test05_where(self):
"""Searching enumerated data."""
tbl = self.h5file.createTable(
'/', 'test', self._description(), title=self._getMethodName())
appended = [
(10, self.valueInEnum),
(20, self.valueInEnum),
(30, self.valueOutOfEnum)]
tbl.append(appended)
tbl.flush()
searched = [
(row['rid'], row['rcolor'])
for row in tbl.where('rcolor == v', {'v': self.valueInEnum}) ]
common.verbosePrint(
"* ``valueInEnum``: %s\n"
"* ``rcolor`` column: ``%s``\n"
"* ``searched``: %s\n"
"* Should look like: %s\n"
% (self.valueInEnum, tbl.cols.rcolor, searched, appended[:-1]))
self.assertEqual(
searched, appended[:-1], "Search returned incorrect results.")
class EnumEArrayTestCase(common.TempFileMixin, common.PyTablesTestCase):
"""Test extendable arrays of enumerated values."""
enum = tables.Enum({'red': 4, 'green': 2, 'blue': 1, 'black': 0})
valueInEnum = enum.red
valueOutOfEnum = 1234
enumType = 'uint16'
def _atom(self, shape=()):
return tables.EnumAtom(
self.enum, 'red', base=self.enumType, shape=shape)
def test00a_reopen(self):
"""Reopening a file with extendable arrays using enumerated data."""
self.h5file.createEArray(
'/', 'test', self._atom(), shape=(0,),
title=self._getMethodName() )
self.h5file.root.test.flavor = 'python'
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum(), self.enum,
"Enumerated type was not restored correctly from disk.")
def test00b_reopenMD(self):
"""
Reopening a file with extendable arrays using enumerated
multi-dimensional data.
"""
self.h5file.createEArray(
'/', 'test', self._atom(), shape=(0, 2),
title=self._getMethodName() )
self.h5file.root.test.flavor = 'python'
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum(), self.enum,
"Enumerated type was not restored correctly from disk.")
def test01_append(self):
"""Appending scalar elements of enumerated values."""
earr = self.h5file.createEArray(
'/', 'test', self._atom(), shape=(0,),
title=self._getMethodName() )
earr.flavor = 'python'
appended = [self.valueInEnum, self.valueOutOfEnum]
earr.append(appended)
earr.flush()
read = earr.read()
self.assertEqual(appended, read, "Written and read values differ.")
def test02_appendMD(self):
"""Appending multi-dimensional elements of enumerated values."""
earr = self.h5file.createEArray(
'/', 'test', self._atom(), shape=(0, 2),
title=self._getMethodName() )
earr.flavor = 'python'
appended = [
[self.valueInEnum, self.valueOutOfEnum],
[self.valueInEnum, self.valueOutOfEnum]]
earr.append(appended)
earr.flush()
read = earr.read()
self.assertEqual(appended, read, "Written and read values differ.")
def test03_setitem(self):
"""Changing enumerated values using ``earray.__setitem__()``."""
earr = self.h5file.createEArray(
'/', 'test', self._atom(), shape=(0,),
title=self._getMethodName() )
earr.flavor = 'python'
appended = (self.valueInEnum, self.valueInEnum)
earr.append(appended)
written = [self.valueInEnum, self.valueOutOfEnum]
earr[:] = written
read = earr.read()
self.assertEqual(written, read, "Written and read values differ.")
class EnumVLArrayTestCase(common.TempFileMixin, common.PyTablesTestCase):
"""Test variable-length arrays of enumerated values."""
enum = tables.Enum({'red': 4, 'green': 2, 'blue': 1, 'black': 0})
valueInEnum = enum.red
valueOutOfEnum = 1234
enumType = 'uint16'
def _atom(self, shape=()):
return tables.EnumAtom(
self.enum, 'red', base=self.enumType, shape=shape)
def test00a_reopen(self):
"""Reopening a file with variable-length arrays using enumerated data."""
self.h5file.createVLArray(
'/', 'test', self._atom(),
title=self._getMethodName() )
self.h5file.root.test.flavor = 'python'
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum(), self.enum,
"Enumerated type was not restored correctly from disk.")
def test00b_reopenMD(self):
"""
Reopening a file with variable-length arrays using enumerated
multi-dimensional data.
"""
self.h5file.createVLArray(
'/', 'test', self._atom((2,)),
title=self._getMethodName() )
self.h5file.root.test.flavor = 'python'
self._reopen()
self.assertEqual(
self.h5file.root.test.getEnum(), self.enum,
"Enumerated type was not restored correctly from disk.")
def test01_append(self):
"""Appending scalar elements of enumerated values."""
vlarr = self.h5file.createVLArray(
'/', 'test', self._atom(),
title=self._getMethodName() )
vlarr.flavor = 'python'
appended = [
[self.valueInEnum,],
[self.valueInEnum, self.valueOutOfEnum]]
vlarr.append(appended[0])
vlarr.append(appended[1])
vlarr.flush()
read = vlarr.read()
common.verbosePrint(
"* appended value: %s\n"
"* read value: %s\n"
% (appended, read) )
self.assertEqual(appended, read, "Written and read values differ.")
def test02_appendMD(self):
"""Appending multi-dimensional elements of enumerated values."""
vlarr = self.h5file.createVLArray(
'/', 'test', self._atom((2,)),
title=self._getMethodName() )
vlarr.flavor = 'python'
appended = [
[[self.valueInEnum, self.valueInEnum],],
[[self.valueInEnum, self.valueOutOfEnum],
[self.valueInEnum, self.valueInEnum]]]
vlarr.append(appended[0])
vlarr.append(appended[1])
vlarr.flush()
read = vlarr.read()
common.verbosePrint(
"* appended value: %s\n"
"* read value: %s\n"
% (appended, read) )
self.assertEqual(appended, read, "Written and read values differ.")
def test03_setitem(self):
"""Changing enumerated values using ``vlarray.__setitem__()``."""
vlarr = self.h5file.createVLArray(
'/', 'test', self._atom(),
title=self._getMethodName() )
vlarr.flavor = 'python'
appended = (self.valueInEnum, self.valueInEnum)
vlarr.append(appended)
written = [self.valueInEnum, self.valueOutOfEnum]
vlarr[0] = written
read = vlarr.read()
common.verbosePrint(
"* written value: %s\n"
"* read value: %s\n"
% (written, read) )
self.assertEqual(written, read[0], "Written and read values differ.")
def suite():
"""Return a test suite consisting of all the test cases in the module."""
# These two are for including Enum's doctests here.
import doctest
from tables.misc import enum
theSuite = unittest.TestSuite()
niter = 1
#theSuite.addTest(unittest.makeSuite(EnumTableTestCase))
for i in range(niter):
theSuite.addTest(doctest.DocTestSuite(enum))
theSuite.addTest(unittest.makeSuite(CreateColTestCase))
theSuite.addTest(unittest.makeSuite(CreateAtomTestCase))
theSuite.addTest(unittest.makeSuite(EnumTableTestCase))
theSuite.addTest(unittest.makeSuite(EnumEArrayTestCase))
theSuite.addTest(unittest.makeSuite(EnumVLArrayTestCase))
return theSuite
if __name__ == '__main__':
unittest.main(defaultTest='suite')
## Local Variables:
## mode: python
## py-indent-offset: 4
## tab-width: 4
## fill-column: 72
## End:
|