Repository navigation
ENH: ensure that dir(astropy) lists subpackages #17598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
06833cb
3de70a8
e84ca54
ebb7711
8fd65e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,54 @@ | |
|
|
||
| from astropy.utils.system_info import system_info | ||
|
|
||
| __all__ = [ # noqa: RUF100, RUF022 | ||
| "__version__", | ||
| "__bibtex__", | ||
| # Subpackages (mostly lazy-loaded) | ||
| "config", | ||
| "constants", | ||
| "convolution", | ||
| "coordinates", | ||
| "cosmology", | ||
| "io", | ||
| "modeling", | ||
| "nddata", | ||
| "samp", | ||
| "stats", | ||
| "table", | ||
| "time", | ||
| "timeseries", | ||
| "uncertainty", | ||
| "units", | ||
| "utils", | ||
| "visualization", | ||
| "wcs", | ||
| # Functions | ||
| "test", | ||
| "log", | ||
| "find_api_page", | ||
| "online_help", | ||
| "online_docs_root", | ||
| "conf", | ||
| "physical_constants", | ||
| "astronomical_constants", | ||
| "system_info", | ||
| ] | ||
|
|
||
|
|
||
| def __getattr__(attr): | ||
| if attr in __all__: | ||
| from importlib import import_module | ||
|
|
||
| return import_module("astropy." + attr) | ||
|
|
||
| raise AttributeError(f"module 'astropy' has no attribute {attr!r}") | ||
|
|
||
|
|
||
| def __dir__(): | ||
| return sorted(set(globals()).union(__all__)) | ||
|
|
||
|
|
||
| from .version import version as __version__ | ||
|
|
||
| # The location of the online documentation for astropy | ||
|
|
@@ -198,30 +246,14 @@ def online_help(query): | |
| webbrowser.open(url) | ||
|
|
||
|
|
||
| __dir_inc__ = [ | ||
| "__version__", | ||
| "__githash__", | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to remove this one since it is not actually defined and EDIT: indeed, this means that once you tab-complete, all subpackages are loaded. I think that's OK, since that's just interactive usage anyway.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think that's how the IPython REPL implements autocompletes for import statements, but I'd like to try it with Python 3.13's new REPL too.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python 3.13's REPL (aka PyREPL) doesn't seem to even try autocompletion in this area, so no change there.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just check and I do get python 3.13.1 to auto-complete
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, indeed, confirmed that that does not work on python 3.13 (but does on ipython); I've noticed before that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. python/cpython#129329 was just merged though I have no idea what Python versions it will land on. Anything we need to follow-up on still?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'll be in 3.14. We can test this further then, but I don't anticipate any follow up to be needed.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the info! I opened #18055 as reminder, just in case. |
||
| "__bibtex__", | ||
| "test", | ||
| "log", | ||
| "find_api_page", | ||
| "online_help", | ||
| "online_docs_root", | ||
| "conf", | ||
| "physical_constants", | ||
| "astronomical_constants", | ||
| "system_info", | ||
| ] | ||
|
|
||
|
|
||
| from types import ModuleType as __module_type__ | ||
|
|
||
| # Clean up top-level namespace--delete everything that isn't in __dir_inc__ | ||
| # Clean up top-level namespace--delete everything that isn't in __all__ | ||
| # or is a magic attribute, and that isn't a submodule of this package | ||
| for varname in dir(): | ||
| if not ( | ||
| (varname.startswith("__") and varname.endswith("__")) | ||
| or varname in __dir_inc__ | ||
| or varname in __all__ | ||
| or ( | ||
| varname[0] != "_" | ||
| and isinstance(locals()[varname], __module_type__) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,14 @@ | ||
| # Licensed under a 3-clause BSD style license - see LICENSE.rst | ||
|
|
||
| import pkgutil | ||
| import subprocess | ||
| import sys | ||
| from textwrap import dedent | ||
| from types import ModuleType | ||
|
|
||
| import pytest | ||
|
|
||
| import astropy | ||
|
|
||
|
|
||
| def test_imports(): | ||
|
|
@@ -32,3 +40,21 @@ def test_toplevel_namespace(): | |
| assert "log" in d | ||
| assert "test" in d | ||
| assert "sys" not in d | ||
|
|
||
|
|
||
| def test_toplevel_lazy_imports(): | ||
| # Check that subpackages are loaded on demand. | ||
| cmd = dedent(""" | ||
| import astropy, sys | ||
| assert 'astropy.units' not in sys.modules | ||
| astropy.units | ||
| assert 'astropy.units' in sys.modules | ||
| """) | ||
| cp = subprocess.check_call([sys.executable, "-c", cmd]) | ||
| assert cp == 0 | ||
|
Comment on lines
+46
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mhvk @pllim looking for other sources of test pollution locally, I hit (I assume by chance) a failure mode for this test. It is extremely puzzling to me that this test might fail in a subprocess, let alone have anything to do with pollution, but unfortunately it is also very hard to debug; I don't even have a good traceback to work with. All I have is So, I'm pinging you guys in the hope that we can figure out a different test for this feature, but I for one don't have a clear idea how. I tried using
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, this should have its own issue. I'll open one now. |
||
|
|
||
|
|
||
| def test_toplevel_attribute_error(): | ||
| # Ensure that our __getattr__ does not leak an import error or so. | ||
| with pytest.raises(AttributeError, match="module 'astropy' has no"): | ||
|
mhvk marked this conversation as resolved.
Resolved
|
||
| astropy.nonsense | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| After ``import astropy``, ``dir(astropy)`` will now list all subpackages, | ||
| including those that have not yet been loaded. This also means tab | ||
| completion will work as expected (e.g., ``from astropy.coo<TAB>`` will | ||
| expand to ``from astropy.coordinates``). |
Uh oh!
There was an error while loading. Please reload this page.