1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# TEST_UNICODE_LITERALS
import sys
import numpy as np
from ...tests.helper import pytest, catch_warnings
from ... import table
from ...table import Row
from ...utils.compat import NUMPY_LT_1_8
from ...utils.exceptions import AstropyDeprecationWarning
from ...extern.six.moves import zip
from .conftest import MaskedTable
def test_masked_row_with_object_col():
"""
Numpy < 1.8 has a bug in masked array that prevents access a row if there is
a column with object type.
"""
t = table.Table([[1]], dtype=['O'], masked=True)
if NUMPY_LT_1_8:
with pytest.raises(ValueError):
t['col0'].mask = False
t[0].as_void()
with pytest.raises(ValueError):
t['col0'].mask = True
t[0].as_void()
else:
t['col0'].mask = False
assert t[0]['col0'] == 1
t['col0'].mask = True
assert t[0]['col0'] is np.ma.masked
@pytest.mark.usefixtures('table_types')
class TestRow():
def _setup(self, table_types):
self._table_type = table_types.Table
self._column_type = table_types.Column
@property
def t(self):
# py.test wants to run this method once before table_types is run
# to set Table and Column. In this case just return None, which would
# cause any downstream test to fail if this happened in any other context.
if self._column_type is None:
return None
if not hasattr(self, '_t'):
a = self._column_type(name='a', data=[1, 2, 3], dtype='i8')
b = self._column_type(name='b', data=[4, 5, 6], dtype='i8')
self._t = self._table_type([a, b])
return self._t
def test_subclass(self, table_types):
"""Row is subclass of ndarray and Row"""
self._setup(table_types)
c = Row(self.t, 2)
assert isinstance(c, Row)
def test_values(self, table_types):
"""Row accurately reflects table values and attributes"""
self._setup(table_types)
table = self.t
row = table[1]
assert row['a'] == 2
assert row['b'] == 5
assert row[0] == 2
assert row[1] == 5
assert row.meta is table.meta
assert row.colnames == table.colnames
assert row.columns is table.columns
with pytest.raises(IndexError):
row[2]
if sys.byteorder == 'little':
assert str(row.dtype) == "[('a', '<i8'), ('b', '<i8')]"
else:
assert str(row.dtype) == "[('a', '>i8'), ('b', '>i8')]"
def test_ref(self, table_types):
"""Row is a reference into original table data"""
self._setup(table_types)
table = self.t
row = table[1]
row['a'] = 10
if table_types.Table is not MaskedTable:
assert table['a'][1] == 10
def test_left_equal(self, table_types):
"""Compare a table row to the corresponding structured array row"""
self._setup(table_types)
np_t = self.t.as_array()
if table_types.Table is MaskedTable:
with pytest.raises(ValueError):
self.t[0] == np_t[0]
else:
for row, np_row in zip(self.t, np_t):
assert np.all(row == np_row)
def test_left_not_equal(self, table_types):
"""Compare a table row to the corresponding structured array row"""
self._setup(table_types)
np_t = self.t.as_array()
np_t['a'] = [0, 0, 0]
if table_types.Table is MaskedTable:
with pytest.raises(ValueError):
self.t[0] == np_t[0]
else:
for row, np_row in zip(self.t, np_t):
assert np.all(row != np_row)
def test_right_equal(self, table_types):
"""Test right equal"""
self._setup(table_types)
np_t = self.t.as_array()
if table_types.Table is MaskedTable:
with pytest.raises(ValueError):
self.t[0] == np_t[0]
else:
for row, np_row in zip(self.t, np_t):
assert np.all(np_row == row)
def test_convert_numpy_array(self, table_types):
self._setup(table_types)
d = self.t[1]
np_data = np.array(d)
if table_types.Table is not MaskedTable:
assert np.all(np_data == d.as_void())
assert np_data is not d.as_void()
assert d.colnames == list(np_data.dtype.names)
np_data = np.array(d, copy=False)
if table_types.Table is not MaskedTable:
assert np.all(np_data == d.as_void())
assert np_data is not d.as_void()
assert d.colnames == list(np_data.dtype.names)
with pytest.raises(ValueError):
np_data = np.array(d, dtype=[(str('c'), 'i8'), (str('d'), 'i8')])
def test_format_row(self, table_types):
"""Test formatting row"""
self._setup(table_types)
table = self.t
row = table[0]
assert repr(row).splitlines() == ['<{0} {1}{2}>'
.format(row.__class__.__name__,
'index=0',
' masked=True' if table.masked else ''),
' a b ',
'int64 int64',
'----- -----',
' 1 4']
assert str(row).splitlines() == [' a b ',
'--- ---',
' 1 4']
assert row._repr_html_().splitlines() == ['<{0} {1}{2}>'
.format(row.__class__.__name__,
'index=0',
' masked=True' if table.masked else ''),
'<table id="table{0}">'.format(id(table)),
'<thead><tr><th>a</th><th>b</th></tr></thead>',
'<thead><tr><th>int64</th><th>int64</th></tr></thead>',
'<tr><td>1</td><td>4</td></tr>',
'</table>']
def test_data_and_as_void(self, table_types):
"""Test the deprecated data property and as_void() method"""
self._setup(table_types)
table = self.t
row = table[0]
# row.data is now deprecated because it is slow, generic and abusable
with catch_warnings(AstropyDeprecationWarning) as warning_lines:
row_data = row.data
assert isinstance(row_data, (np.void, np.ma.mvoid))
assert warning_lines[0].category == AstropyDeprecationWarning
assert ("The data function is deprecated" in str(warning_lines[0].message))
# If masked then with no masks, issue numpy/numpy#483 should come into play.
# Make sure as_void() code is working.
row_void = row.as_void()
if table.masked:
assert isinstance(row_void, np.ma.mvoid)
else:
assert isinstance(row_void, np.void)
assert row_void['a'] == 1
assert row_void['b'] == 4
# Confirm row is a view of table but row_void is not.
table['a'][0] = -100
assert row['a'] == -100
assert row_void['a'] == 1
# Make sure it works for a table that has masked elements
if table.masked:
table['a'].mask = True
# row_void is not a view, need to re-make
assert row_void['a'] == 1
row_void = row.as_void() # but row is a view
assert row['a'] is np.ma.masked
def test_row_and_as_void_with_objects(self, table_types):
"""Test the deprecated data property and as_void() method"""
t = table_types.Table([[{'a': 1}, {'b': 2}]], names=('a',))
assert t[0][0] == {'a': 1}
assert t[0]['a'] == {'a': 1}
if NUMPY_LT_1_8 and t.masked:
# With numpy < 1.8 there is a bug setting mvoid with
# an object.
with pytest.raises(ValueError):
t[0].as_void()
else:
assert t[0].as_void()[0] == {'a': 1}
assert t[0].as_void()['a'] == {'a': 1}
def test_bounds_checking(self, table_types):
"""Row gives index error upon creation for out-of-bounds index"""
self._setup(table_types)
for ibad in (-5, -4, 3, 4):
with pytest.raises(IndexError):
self.t[ibad]
|