Skip to content
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

Make IPython partially optional on CI to increase test coverage of figure.py #1496

Merged
merged 13 commits into from
Sep 20, 2021

Conversation

weiji14
Copy link
Member

@weiji14 weiji14 commented Sep 12, 2021

Description of proposed changes

The pygmt/figure.py file has the smallest code coverage in the PyGMT project, with 15 lines uncovered. This is mostly due to if-branches that only get triggered when IPython isn't installed.

image

This PR makes IPython an optional dependency in Continuous Integration for the minimum dependency stream (Python 3.7/NumPy 1.18), so that those uncovered if-branches are covered. Tests which require IPython will have a pytest.importorskip line added so that the test suite doesn't break.

See coverage diff at https://app.codecov.io/gh/GenericMappingTools/pygmt/compare/1496/changes. Project test coverage increased by 0.96% to 98.25%!

References:

Addresses #1247 (comment) and patches #529 with more code coverage.

Reminders

  • Run make format and make check to make sure the code follows the style guide.
  • Add tests for new features or tests that would have caught the bug that you're fixing.
  • Add new public functions/methods/classes to doc/api/index.rst.
  • Write detailed docstrings for all functions/methods.
  • If adding new functionality, add an example to docstrings or tutorials.

Slash Commands

You can write slash commands (/command) in the first line of a comment to perform
specific operations. Supported slash commands are:

  • /format: automatically format and lint the code
  • /test-gmt-dev: run full tests on the latest GMT development version

@weiji14 weiji14 added the maintenance Boring but important stuff for the core devs label Sep 12, 2021
@weiji14 weiji14 self-assigned this Sep 12, 2021
@weiji14 weiji14 changed the title Increase test coverage on figure.py WIP: Increase test coverage on figure.py Sep 14, 2021
@weiji14 weiji14 marked this pull request as ready for review September 18, 2021 02:49
@weiji14 weiji14 changed the title WIP: Increase test coverage on figure.py Make IPython partially optional on CI to increase test coverage of figure.py Sep 18, 2021
@seisman seisman added this to the 0.5.0 milestone Sep 18, 2021
fig.basemap(region=[0, 1, 2, 3], frame=True)
# Check that correct PNG 8-byte file header is produced
# https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header
repr_png = fig._repr_png_() # pylint: disable=protected-access
Copy link
Member

Choose a reason for hiding this comment

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

Is _repr_png_ and _repr_html_ useful? I have no idea how these functions can be used.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good question. They are used by IPython.display.display_png and IPython.display.display_html respectively, i.e. for display in Jupyter notebooks.

Technically I should have written these unit test using IPython.display.display_png(fig) and IPython.display.display_html(fig) instead of testing these non-public functions directly, but it's hard to test a pop-up figure. So I've settled for testing the __repr_png__ and __repr_html__ instead (which works with or without IPython installed). Con with this approach is that I need to do pylint: disable=protected-access 🙃

Copy link
Member

Choose a reason for hiding this comment

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

They are used by IPython.display.display_png and IPython.display.display_html respectively, i.e. for display in Jupyter notebooks.

PyGMT already provides the Figure.show() function for display in Jupyter notebooks. Removing _repr_png_() and _repr_html_() doesn't affect the Figure.show() function. Do you think we should remove these two functions?

Copy link
Member Author

Choose a reason for hiding this comment

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

It might not affect Figure.show(), but I think we need to keep it. Having __repr_png__() and __repr_html__ means that putting just fig at the last line of a Jupyter notebook cell will display the plot. E.g. like this:

image

This works in Jupyter/IPython because of a IPython.display.display_html(fig) call. Similarly, if you put a df (pandas.DataFrame) on the last line of a cell, a nicely formatted html table will be printed because Jupyter/IPython does IPython.display.display_html(df) (see the __repr_html__ at https://github.com/pandas-dev/pandas/blob/73c68257545b5f8530b7044f56647bd2db92e2ba/pandas/core/frame.py#L1007-L1049).

pygmt/tests/test_figure.py Outdated Show resolved Hide resolved
weiji14 and others added 2 commits September 20, 2021 11:24
Co-Authored-By: Dongdong Tian <seisman.info@gmail.com>
Comment on lines +238 to +244
def test_figure_display_external():
"""
Test to check that a figure can be displayed in an external window.
"""
fig = Figure()
fig.basemap(region=[0, 3, 6, 9], projection="X1c", frame=True)
fig.show(method="external")
Copy link
Member

Choose a reason for hiding this comment

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

The CI can't open external viewers. Why does this test work?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, the console won't show a window pop-up, but I think the code will still execute fine somehow. Looking at the codecov diff at https://app.codecov.io/gh/GenericMappingTools/pygmt/compare/1496/changes#D2L237, the launch_external_viewer function is being called up to the time.sleep(0.5) line, so it seems that Linux/macOS/Windows launchers (xdg-open/open/not-sure-what's-on windows) are available on CI?

image

@seisman seisman added the final review call This PR requires final review and approval from a second reviewer label Sep 20, 2021
@weiji14 weiji14 merged commit c0a8dfa into main Sep 20, 2021
@weiji14 weiji14 deleted the optional-ipython-tests branch September 20, 2021 22:31
@weiji14 weiji14 removed the final review call This PR requires final review and approval from a second reviewer label Sep 20, 2021
sixy6e pushed a commit to sixy6e/pygmt that referenced this pull request Dec 21, 2022
…gure.py (GenericMappingTools#1496)

Makes IPython an optional dependency in Continuous Integration
for the minimum dependency stream (Python 3.7/NumPy 1.18),
so that uncovered if-branches in `figure.py` are covered. Tests
which require IPython have a pytest.importorskip line added so
that the test suite doesn't break.

* Install IPython as an optional dependency only for Python 3.9 CI tests
* Add pytest.importorskip ipython to test_figure_show
* Add pytest.importorskip ipython and sphinx_gallery to test_pygmtscrapper
* Skip running the fig.inset doctest's fig.show line
* Add test for fig.show using notebook method when IPython isn't installed
* Add tests for figure's PNG and HTML printable representations
* Provide reason for skipping test_figure_show and test_pygmtscrapper
* Silence pylint protected-access warning on accessing PNG and HTML repr
* Try test figure display external method
* Move pytest.importorskip IPython outside of test_pygmtscrapper

Co-authored-by: Dongdong Tian <seisman.info@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintenance Boring but important stuff for the core devs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants