-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
I don't know why I never encountered this until now, but recently some of the astropy.io.votable tests started failing for me, in particular on Python 2.6, though the general problem affects other Python versions.
The problem is this: astropy/table/__init__.py tries to import all the modules that make an I/O registry connection with table:
# Import routines that connect readers/writers to astropy.table
from ..io.ascii import connect
from ..io.fits import connect
from ..io.misc import connect
from ..io.votable import connect
Each of these connect modules in turn import from ..table import Table since they use the I/O registry mechanism to register themselves on the Table class. This work out okay so long as the import happens in this order, because by the time the from <> import connect statements are executed an entry already exists in sys.modules['astropy.table'] and the Table class has been imported into that namespace. No problem there.
The problem occurs (and this has been happening when I run the tests on Python 2.6, so it depends very much on the exact order in which the tests are run) if you try to import, for example, astropy.io.votable.connect before importing astropy.table you will get an impot error:
>>> import astropy.io.votable.connect
ERROR: ImportError: cannot import name connect [unknown]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "astropy/io/votable/connect.py", line 12, in <module>
from ...table import Table
File "astropy/table/__init__.py", line 10, in <module>
from ..io.votable import connect
ImportError: cannot import name connect
There aren't many reasons for a user to do this but it can happen in the tests, and may be responsible for some random-ish failures when running the tests in parallel.
The reason for this failure is subtle: When you import astropy.io.votable.connect a stub entries for that module and for astropy.io.votable are created. Once in the connect module the statement to from ..table import Table is executed, which runs through astropy.table.__init__. When that reaches from ..io.votable import connect this fails, because although the module has an entry in sys.modules, for this exact statement to work the astropy.io.votable has to have an entry for the connect module in its __dict__, which will only get created once the connect module has finished importing, which has not yet happened.
I believe this can be worked around--several hacky ways already come to mind. But I'd prefer a less hacky way, even if that means some refactoring.