Skip to content

Commit dcaf1a6

Browse files
committed
Only load required I/O functions at the last minute
1 parent 2bd5701 commit dcaf1a6

7 files changed

Lines changed: 66 additions & 54 deletions

File tree

astropy/io/ascii/connect.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,11 @@ def read_asciitable(filename, **kwargs):
2020
from .ui import read
2121
return read(filename, **kwargs)
2222

23-
io_registry.register_reader('ascii', Table, read_asciitable)
24-
2523

2624
def write_asciitable(table, filename, **kwargs):
2725
from .ui import write
2826
return write(table, filename, **kwargs)
2927

30-
io_registry.register_writer('ascii', Table, write_asciitable)
31-
3228

3329
def io_read(format, filename, **kwargs):
3430
from .ui import read
@@ -44,27 +40,3 @@ def io_write(format, table, filename, **kwargs):
4440

4541
def io_identify(suffix, origin, filepath, fileobj, *args, **kwargs):
4642
return filepath is not None and filepath.endswith(suffix)
47-
48-
49-
def _get_connectors_table():
50-
from .core import FORMAT_CLASSES
51-
52-
rows = []
53-
rows.append(('ascii', '', 'Yes', 'ASCII table in any supported format (uses guessing)'))
54-
for format in sorted(FORMAT_CLASSES):
55-
cls = FORMAT_CLASSES[format]
56-
57-
io_format = 'ascii.' + cls._format_name
58-
description = getattr(cls, '_description', '')
59-
class_link = ':class:`~{}.{}`'.format(cls.__module__, cls.__name__)
60-
suffix = getattr(cls, '_io_registry_suffix', '')
61-
can_write = 'Yes' if getattr(cls, '_io_registry_can_write', True) else ''
62-
63-
rows.append((io_format, suffix, can_write,
64-
'{}: {}'.format(class_link, description)))
65-
out = Table(list(zip(*rows)), names=('Format', 'Suffix', 'Write', 'Description'))
66-
for colname in ('Format', 'Description'):
67-
width = max(len(x) for x in out[colname])
68-
out[colname].format = '%-{}s'.format(width)
69-
70-
return out

astropy/io/fits/connect.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,3 @@ def write_table_fits(input, output, overwrite=False):
292292

293293
# Write out file
294294
table_hdu.writeto(output)
295-
296-
io_registry.register_reader('fits', Table, read_table_fits)
297-
io_registry.register_writer('fits', Table, write_table_fits)
298-
io_registry.register_identifier('fits', Table, is_fits)

astropy/io/misc/connect.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,4 @@
88
from .hdf5 import read_table_hdf5, write_table_hdf5, is_hdf5
99

1010
from .. import registry as io_registry
11-
from ...table import Table
12-
13-
io_registry.register_reader('hdf5', Table, read_table_hdf5)
14-
io_registry.register_writer('hdf5', Table, write_table_hdf5)
15-
io_registry.register_identifier('hdf5', Table, is_hdf5)
11+
from ...table import Table

astropy/io/registry.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,54 @@
1919

2020
__doctest_skip__ = ['register_identifier']
2121

22-
22+
_builtin_registered = False
2323
_readers = OrderedDict()
2424
_writers = OrderedDict()
2525
_identifiers = OrderedDict()
2626

27+
# Add built-in readers/writers to the registry manually, and refer to the
28+
# functions by strings to avoid importing those modules.
29+
def _register_builtins():
30+
31+
global _builtin_registered
32+
33+
if not _builtin_registered:
34+
35+
from ..table import Table
36+
37+
_builtin_registered = True
38+
39+
# FITS
40+
register_reader("fits", Table, 'astropy.io.fits.connect.read_table_fits')
41+
register_writer("fits", Table, 'astropy.io.fits.connect.write_table_fits')
42+
register_identifier("fits", Table, 'astropy.io.fits.connect.is_fits')
43+
44+
# VOTABLE
45+
register_reader('votable', Table, 'astropy.io.votable.connect.read_table_votable')
46+
register_writer('votable', Table, 'astropy.io.votable.connect.write_table_votable')
47+
register_identifier('votable', Table, 'astropy.io.votable.connect.is_votable')
48+
49+
# HDF5
50+
register_reader('hdf5', Table, 'astropy.io.misc.hdf5.read_table_hdf5')
51+
register_writer('hdf5', Table, 'astropy.io.misc.hdf5.write_table_hdf5')
52+
register_identifier('hdf5', Table, 'astropy.io.misc.hdf5.is_hdf5')
53+
54+
# JSViewer
55+
register_writer('jsviewer', Table, 'astropy.table.jsviewer.write_table_jsviewer')
56+
57+
# ASCII
58+
register_reader('ascii', Table, 'astropy.io.ascii.connect.read_asciitable')
59+
register_writer('ascii', Table, 'astropy.io.ascii.connect.write_asciitable')
60+
61+
# Remaining ASCII formats - for now can only import io.ascii to force
62+
# meta-classes to register.
63+
from . import ascii
64+
65+
def _get_function_by_string(path_to_function):
66+
import importlib
67+
module, function = path_to_function.rsplit('.', 1)
68+
return getattr(importlib.import_module(module), function)
69+
2770

2871
def get_formats(data_class=None):
2972
"""
@@ -39,6 +82,9 @@ def get_formats(data_class=None):
3982
format_table: Table
4083
Table of available I/O formats
4184
"""
85+
86+
_register_builtins()
87+
4288
from ..table import Table
4389
format_classes = sorted(set(_readers) | set(_writers),
4490
key=lambda tup: tup[0])
@@ -242,11 +288,16 @@ def register_identifier(data_format, data_class, identifier, force=False):
242288

243289

244290
def identify_format(origin, data_class_required, path, fileobj, args, kwargs):
291+
_register_builtins()
245292
# Loop through identifiers to see which formats match
246293
valid_formats = []
247294
for data_format, data_class in _identifiers:
248295
if _is_best_match(data_class_required, data_class, _identifiers):
249-
if _identifiers[(data_format, data_class)](
296+
identifier = _identifiers[(data_format, data_class)]
297+
if isinstance(identifier, six.string_types):
298+
identifier = _get_function_by_string(identifier)
299+
_identifiers[(data_format, data_class)] = identifier
300+
if identifier(
250301
origin, path, fileobj, *args, **kwargs):
251302
valid_formats.append(data_format)
252303

@@ -264,11 +315,16 @@ def _get_format_table_str(data_class, readwrite):
264315

265316

266317
def get_reader(data_format, data_class):
318+
_register_builtins()
267319
# Get all the readers that work for `data_format`
268320
readers = [(fmt, cls) for fmt, cls in _readers if fmt == data_format]
269321
for reader_format, reader_class in readers:
270322
if _is_best_match(data_class, reader_class, readers):
271-
return _readers[(reader_format, reader_class)]
323+
reader = _readers[(reader_format, reader_class)]
324+
if isinstance(reader, six.string_types):
325+
reader = _get_function_by_string(reader)
326+
_readers[(reader_format, reader_class)] = reader
327+
return reader
272328
else:
273329
format_table_str = _get_format_table_str(data_class, 'Read')
274330
raise Exception("No reader defined for format '{0}' and class '{1}'.\n"
@@ -278,10 +334,15 @@ def get_reader(data_format, data_class):
278334

279335

280336
def get_writer(data_format, data_class):
337+
_register_builtins()
281338
writers = [(fmt, cls) for fmt, cls in _writers if fmt == data_format]
282339
for writer_format, writer_class in writers:
283340
if _is_best_match(data_class, writer_class, writers):
284-
return _writers[(writer_format, writer_class)]
341+
writer = _writers[(writer_format, writer_class)]
342+
if isinstance(writer, six.string_types):
343+
writer = _get_function_by_string(writer)
344+
_writers[(writer_format, writer_class)] = writer
345+
return writer
285346
else:
286347
format_table_str = _get_format_table_str(data_class, 'Write')
287348
raise Exception("No writer defined for format '{0}' and class '{1}'.\n"

astropy/io/votable/connect.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,3 @@ def write_table_votable(input, output, table_id=None, overwrite=False,
151151

152152
# Write out file
153153
table_file.to_xml(output, tabledata_format=tabledata_format)
154-
155-
156-
io_registry.register_reader('votable', Table, read_table_votable)
157-
io_registry.register_writer('votable', Table, write_table_votable)
158-
io_registry.register_identifier('votable', Table, is_votable)

astropy/table/__init__.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,3 @@ class Conf(_config.ConfigNamespace):
2424
from .np_utils import TableMergeError
2525
from .operations import join, hstack, vstack
2626

27-
# Import routines that connect readers/writers to astropy.table
28-
from ..io.ascii import connect
29-
from ..io.fits import connect
30-
from ..io.misc import connect
31-
from ..io.votable import connect
32-
from . import jsviewer

astropy/table/jsviewer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,3 @@ def write_table_jsviewer(table, filename, table_id=None,
172172
htmldict['js'] = jsv.html_js(table_id=table_id)
173173

174174
table.write(filename, format='html', htmldict=htmldict)
175-
176-
io_registry.register_writer('jsviewer', Table, write_table_jsviewer)

0 commit comments

Comments
 (0)