Skip to content

Speed up wcsaxes import by avoiding unnecessary pytest import#10302

Closed
lpsinger wants to merge 1 commit intoastropy:mainfrom
lpsinger:pytest-speed-up-import
Closed

Speed up wcsaxes import by avoiding unnecessary pytest import#10302
lpsinger wants to merge 1 commit intoastropy:mainfrom
lpsinger:pytest-speed-up-import

Conversation

@lpsinger
Copy link
Contributor

@lpsinger lpsinger commented May 4, 2020

In astropy.visualization.wcsaxes, do not import pytest unless we are actually running the tests. Pytest is a fairly heavyweight import, so it should not be imported unless it's actually needed.

mhvk
mhvk previously approved these changes May 4, 2020
Copy link
Contributor

@mhvk mhvk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this simply seems wrong. I'm confident enough to approve, but it would be good for @astrofrog to review, since he added it here.

@mhvk
Copy link
Contributor

mhvk commented May 4, 2020

@lpsinger - if you did notice other cases, and have time, definitely tell where or open other PRs.

@lpsinger
Copy link
Contributor Author

lpsinger commented May 4, 2020

Unfortunately, the conftest.py doesn't work. I'm trying a few different strategies here.

@mhvk
Copy link
Contributor

mhvk commented May 4, 2020

Might it work in tests/__init__.py?

@mhvk mhvk dismissed their stale review May 4, 2020 20:21

Approval was premature

@mhvk
Copy link
Contributor

mhvk commented May 4, 2020

Hmm, I think I'm starting to see the problem (never think @astrofrog did strange looking things for no reason..). pytest probably traverses the tree and tries to import things, just to look for tests.

But perhaps one can avoid loading pytest by trying to import matplotlib in __init__.py and if that fails do the pytest.importorskip step? By that time, the user is most likely trying to import something from wcsaxes anyway, so if matplotlib is not present, they are getting a failure regardless and the time doesn't matter so much.

Aside: pytest used to be just a single file which we shipped, hardly a heavy dependence!

@mhvk
Copy link
Contributor

mhvk commented May 4, 2020

p.s. I cancelled travis to save some cycles, since you wrote things didn't work.

@lpsinger lpsinger force-pushed the pytest-speed-up-import branch from d0df5e6 to 4868eda Compare May 4, 2020 20:39
@pep8speaks
Copy link

pep8speaks commented May 4, 2020

Hello @lpsinger 👋! It looks like you've made some changes in your pull request, so I've checked the code again for style.

There are no PEP8 style issues with this pull request - thanks! 🎉

Comment last updated at 2020-05-04 21:18:18 UTC

@lpsinger
Copy link
Contributor Author

lpsinger commented May 4, 2020

@mhvk, @bsipocz, I force-pushed a new implementation. Please take a look and send feedback. If you like it, I'll clean it up, make the same change for all other impacted modules, and add a changelog entry.

In `astropy.visualization.wcsaxes`, do not import pytest unless
we are actually running the tests. Pytest is a fairly heavyweight
import, so it should not be imported unless it's actually needed.
@lpsinger lpsinger force-pushed the pytest-speed-up-import branch from 4868eda to 43fea65 Compare May 4, 2020 21:18
@lpsinger lpsinger changed the title WIP: Speed up astropy imports by moving pytest skips to conftest.py Speed up wcsaxes import by avoiding unnecessary pytest import May 4, 2020

if tests.RUNNING:
import pytest
pytest.importorskip("matplotlib")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait a minute. Why is this even here? It should have been in the individual test modules under tests. Looks like we inherited this from the package we absorbed in #5496. @astrofrog , do you remember why this is at subpackage init level and not the tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that this is because wcsaxes is unique in Astropy in that it subclasses many different Matplotlib subclasses, and so the conditional imports of the kind in astropy.visualization.mpl_normalize were not appropriate:

try:
    import matplotlib  # pylint: disable=W0611
    from matplotlib.colors import Normalize
    from matplotlib import pyplot as plt
except ImportError:
    class Normalize:
        def __init__(self, *args, **kwargs):
            raise ImportError('matplotlib is required in order to use this '
                              'class.')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it was a convenient way to make sure mpl is needed for the whole module and skip it at collection time at the earliest and quickest way possible. Fully agreed that it should not be used like this.

Copy link
Member

@pllim pllim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a feeling that this is not the correct solution. See my comment above. Thanks for bringing this to our attention!

@mhvk
Copy link
Contributor

mhvk commented May 4, 2020

@lpsinger - that feels too hacky, modifying some almost global state. I also worry that things like pytest astropy/visualization will not be covered. My suggestion above might be better, but I agree with @pllim that at this point it would be good to get @astrofrog's opinion, since he almost certainly struggled with this when moving wcsaxes over here.

Also, which other modules have things like this? Maybe some of those can more easily be changed? Because you are definitely right that we should not be importing pytest anywhere but in tests directories!

@lpsinger
Copy link
Contributor Author

lpsinger commented May 4, 2020

Also, which other modules have things like this? Maybe some of those can more easily be changed? Because you are definitely right that we should not be importing pytest anywhere but in tests directories!

Happily, this is the only such module in Astropy itself.

@pllim
Copy link
Member

pllim commented May 5, 2020

I feel like the more correct solution would be something like #10260 but it is a lot more work and is borderline controversial to some people.

I mean, if we make yaml, asdf, etc go through strict import checks in io.misc, why not here as well? matplotlib is just as optional as those packages.

@mhvk
Copy link
Contributor

mhvk commented May 5, 2020

Agree with the sentiment, though there are lots of modules here which use it, and having the whole module indented becomes a bit much! But perhaps there are cleverer solutions?

@pllim
Copy link
Member

pllim commented May 5, 2020

Well, in the PR for asdf linked above, the dependency namespace is replaced with generic junk, which would make the import work fine without dependency installed, but you get exception when you actually try to use the stuff for real. So the tradeoff is no error on import but you don't get told you are missing a dependency until later. 🤷 This game is hard to win.

@astropy-bot
Copy link

astropy-bot bot commented Oct 7, 2020

Hi humans 👋 - this pull request hasn't had any new commits for approximately 5 months. I plan to close this in a month if the pull request doesn't have any new commits by then.

In lieu of a stalled pull request, please consider closing this and open an issue instead if a reminder is needed to revisit in the future. Maintainers may also choose to add keep-open label to keep this PR open but it is discouraged unless absolutely necessary.

If this PR still needs to be reviewed, as an author, you can rebase it to reset the clock.

If you believe I commented on this pull request incorrectly, please report this here.

@astrofrog astrofrog modified the milestones: v4.0.2, v4.0.3, v4.0.4 Oct 10, 2020
@bsipocz bsipocz modified the milestones: v4.0.4, v4.0.5 Nov 25, 2020
@eteq eteq modified the milestones: v4.0.5, v4.0.6 Mar 18, 2021
@lpsinger
Copy link
Contributor Author

lpsinger commented Apr 7, 2021

I see that this has been re-milestoned several times. Would you like me to rebase it?

@pllim
Copy link
Member

pllim commented Apr 7, 2021

@lpsinger , thanks for pinging us. Personally, I am not convinced that this is the correct solution.

It is weird that the pytest.importorskip("matplotlib") is in __init__.py of a non-test code, so that definitely needs to be fixed, but not like this. Perhaps @astrofrog or @Cadair can provide some insight.

@astrofrog
Copy link
Member

astrofrog commented Apr 7, 2021

I wonder if we could use

doctest_subpackage_requires =
to prevent issues with pytest when matplotlib is not installed? (Not at computer so can't check right now)

@lpsinger
Copy link
Contributor Author

lpsinger commented Apr 7, 2021

FWIW, I tried putting the pytest.importorskip in a conftest.py module, and it didn't work.

@lpsinger
Copy link
Contributor Author

lpsinger commented Apr 7, 2021

I wonder if we could use

doctest_subpackage_requires =

to prevent issues with pytest when matplotlib is not installed? (Not at computer so can't check right now)

Just tried that. Didn't work.

@pllim
Copy link
Member

pllim commented Apr 7, 2021

What about moving pytest.importorskip("matplotlib") to each of the affected test modules, and deleting it from __init__.py? Sure, it is more duplication but it is more correct, no?

@lpsinger
Copy link
Contributor Author

lpsinger commented Apr 7, 2021

What about moving pytest.importorskip("matplotlib") to each of the affected test modules, and deleting it from __init__.py? Sure, it is more duplication but it is more correct, no?

That would not work. The import errors occur during collection, not while running the tests.

@pllim
Copy link
Member

pllim commented Apr 7, 2021

The import errors occur during collection

Ah, right, that rings a faraway bell now.

Sigh... How does io.misc do it? I mean, they use optional dependencies too and I don't see pytest imported in astropy/io/misc/asdf/__init__.py

@astrofrog astrofrog modified the milestones: v4.0.6, v4.0.7 Aug 24, 2021
@github-actions github-actions bot added the Close? Tell stale bot that this issue/PR is stale label Sep 3, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Sep 4, 2021

Hi humans 👋 - this pull request hasn't had any new commits for approximately 1 year, 4 months. I plan to close this in 30 days if the pull request doesn't have any new commits by then.

In lieu of a stalled pull request, please consider closing this and open an issue instead if a reminder is needed to revisit in the future. Maintainers may also choose to add keep-open label to keep this PR open but it is discouraged unless absolutely necessary.

If this PR still needs to be reviewed, as an author, you can rebase it to reset the clock.

If you believe I commented on this pull request incorrectly, please report this here.

@github-actions github-actions bot added the closed-by-bot Closed by stale bot label Oct 5, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Oct 5, 2021

I'm going to close this pull request as per my previous message. If you think what is being added/fixed here is still important, please remember to open an issue to keep track of it. Thanks!

If this is the first time I am commenting on this issue, or if you believe I closed this issue incorrectly, please report this here.

@github-actions github-actions bot closed this Oct 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants