Skip to content

Commit

Permalink
Merge pull request #7213 from saimn/fix-table-subclass
Browse files Browse the repository at this point in the history
 Fix issue with serialization when using a Table subclass
  • Loading branch information
taldcroft committed Mar 8, 2018
2 parents d80fbda + 29c43e8 commit 9626265
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ astropy.io.misc
astropy.io.registry
^^^^^^^^^^^^^^^^^^^

- Fix reading files with serialized metadata when using a Table subclass. [#7213]

astropy.io.votable
^^^^^^^^^^^^^^^^^^

Expand Down
20 changes: 8 additions & 12 deletions astropy/io/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,18 +517,14 @@ def read(cls, *args, format=None, **kwargs):
data = reader(*args, **kwargs)

if not isinstance(data, cls):
if issubclass(cls, data.__class__):
# User has read with a subclass where only the parent class is
# registered. This returns the parent class, so try coercing
# to desired subclass.
try:
data = cls(data)
except Exception:
raise TypeError('could not convert reader output to {0} '
'class.'.format(cls.__name__))
else:
raise TypeError("reader should return a {0} instance"
"".format(cls.__name__))
# User has read with a subclass where only the parent class is
# registered. This returns the parent class, so try coercing
# to desired subclass.
try:
data = cls(data)
except Exception:
raise TypeError('could not convert reader output to {0} '
'class.'.format(cls.__name__))
finally:
if ctx is not None:
ctx.__exit__(*sys.exc_info())
Expand Down
43 changes: 34 additions & 9 deletions astropy/io/tests/test_registry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst



import os
from copy import copy
from io import StringIO
Expand All @@ -12,11 +10,18 @@
from ..registry import _readers, _writers, _identifiers
from .. import registry as io_registry
from ...table import Table
from ... import units as u

_READERS_ORIGINAL = copy(_readers)
_WRITERS_ORIGINAL = copy(_writers)
_IDENTIFIERS_ORIGINAL = copy(_identifiers)

try:
import yaml # pylint: disable=W0611
HAS_YAML = True
except ImportError:
HAS_YAML = False


class TestData:
read = classmethod(io_registry.read)
Expand Down Expand Up @@ -317,13 +322,6 @@ def test_read_valid_return():
assert isinstance(t, TestData)


def test_read_invalid_return():
io_registry.register_reader('test', TestData, lambda: 'spam')
with pytest.raises(TypeError) as exc:
TestData.read(format='test')
assert str(exc.value) == "reader should return a TestData instance"


def test_non_existing_unknown_ext():
"""Raise the correct error when attempting to read a non-existing
file with an unknown extension."""
Expand Down Expand Up @@ -410,3 +408,30 @@ class MyTable(Table):
mt = MyTable([[1], [2]], names=['a', 'b'])
mt.write(buffer, format='ascii')
assert buffer.getvalue() == os.linesep.join(['a b', '1 2', ''])

def test_read_table_subclass_with_columns_attributes(self, tmpdir):
"""Regression test for https://github.com/astropy/astropy/issues/7181
"""

class MTable(Table):
pass

mt = MTable([[1, 2.5]], names=['a'])
mt['a'].unit = u.m
mt['a'].format = '.4f'
mt['a'].description = 'hello'

testfile = str(tmpdir.join('junk.fits'))
mt.write(testfile, overwrite=True)

t = MTable.read(testfile)
assert np.all(mt == t)
assert mt.colnames == t.colnames
assert type(t) is MTable
assert t['a'].unit == u.m
if HAS_YAML:
assert t['a'].format == '.4f'
assert t['a'].description == 'hello'
else:
assert t['a'].format is None
assert t['a'].description is None

0 comments on commit 9626265

Please sign in to comment.