diff --git a/doc/Makefile b/doc/Makefile index b82215c44c4..04b1c1ab549 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,14 +1,12 @@ # Makefile for Sphinx documentation # You can set these variables from the command line. -SPHINXOPTS = -j auto -SPHINXBUILD = sphinx-build +SPHINXOPTS ?= -j auto +SPHINXBUILD ?= sphinx-build SPHINXAUTOGEN = sphinx-autogen +SOURCEDIR = . BUILDDIR = _build -# Internal variables. -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(SPHINXOPTS) . - .PHONY: help all api html server clean help: @@ -28,20 +26,20 @@ api: @echo $(SPHINXAUTOGEN) -i -t _templates -o api/generated api/*.rst -html: api +html latex: api @echo - @echo "Building HTML files." + @echo "Building "$@" files." @echo # Set PYGMT_USE_EXTERNAL_DISPLAY to "false" to disable external display - PYGMT_USE_EXTERNAL_DISPLAY="false" $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + PYGMT_USE_EXTERNAL_DISPLAY="false" $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + @echo "Build finished. The files are in $(BUILDDIR)/$@." html-noplot: api @echo @echo "Building HTML files without example plots." @echo - $(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) -D plot_gallery=0 @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/doc/conf.py b/doc/conf.py index 2b41acd3f61..f3cb59228c2 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -210,12 +210,10 @@ repository = "GenericMappingTools/pygmt" repository_url = "https://github.com/GenericMappingTools/pygmt" if __commit__: - commit_link = ( - f'{ __commit__[:8] }' - ) + commit_link = f'{__commit__[:8]}' else: commit_link = ( - f'{ __version__ }' + f'{__version__}' ) html_context = { "menu_links": [ diff --git a/environment.yml b/environment.yml index ce30de4825c..c51b2967fc2 100644 --- a/environment.yml +++ b/environment.yml @@ -27,7 +27,7 @@ dependencies: # Dev dependencies (style checks) - codespell - pre-commit - - ruff>=0.8.2 + - ruff>=0.9.0 # Dev dependencies (unit testing) - matplotlib-base - pytest>=6.0 diff --git a/examples/tutorials/advanced/cartesian_histograms.py b/examples/tutorials/advanced/cartesian_histograms.py index 7191d18cbfd..3a547fd92f5 100644 --- a/examples/tutorials/advanced/cartesian_histograms.py +++ b/examples/tutorials/advanced/cartesian_histograms.py @@ -348,7 +348,7 @@ # of the bin width # Offset ("+o") the bars to align each bar with the left limit of the corresponding # bin - barwidth=f"{binwidth/2}+o-{binwidth/4}", + barwidth=f"{binwidth / 2}+o-{binwidth / 4}", label="data01", ) @@ -359,7 +359,7 @@ fill="orange", pen="1p,darkgray,solid", histtype=0, - barwidth=f"{binwidth/2}+o{binwidth/4}", + barwidth=f"{binwidth / 2}+o{binwidth / 4}", label="data02", ) diff --git a/pygmt/_show_versions.py b/pygmt/_show_versions.py index d15bf0799c6..f0d4b4e3c2f 100644 --- a/pygmt/_show_versions.py +++ b/pygmt/_show_versions.py @@ -16,7 +16,7 @@ from pygmt.clib import Session, __gmt_version__ # Get semantic version through setuptools-scm -__version__ = f'v{version("pygmt")}' # e.g. v0.1.2.dev3+g0ab3cd78 +__version__ = f"v{version('pygmt')}" # e.g. v0.1.2.dev3+g0ab3cd78 __commit__ = __version__.split("+g")[-1] if "+g" in __version__ else "" # 0ab3cd78 diff --git a/pygmt/clib/conversion.py b/pygmt/clib/conversion.py index b7f05a9d719..4a52afb497b 100644 --- a/pygmt/clib/conversion.py +++ b/pygmt/clib/conversion.py @@ -205,10 +205,11 @@ def _to_numpy(data: Any) -> np.ndarray: array = np.ascontiguousarray(data, dtype=numpy_dtype) - # Check if a np.object_ / np.str_ array can be converted to np.datetime64. + # Check if a np.object_ or np.str_ array can be converted to np.datetime64. if array.dtype.type in {np.object_, np.str_}: with contextlib.suppress(TypeError, ValueError): return np.ascontiguousarray(array, dtype=np.datetime64) + # Check if a np.object_ array can be converted to np.str_. if array.dtype == np.object_: with contextlib.suppress(TypeError, ValueError): diff --git a/pygmt/encodings.py b/pygmt/encodings.py index 0c7b7ddc895..09c749c4c82 100644 --- a/pygmt/encodings.py +++ b/pygmt/encodings.py @@ -1,3 +1,4 @@ +# noqa: A005 """ Character encodings supported by GMT. diff --git a/pygmt/helpers/tempfile.py b/pygmt/helpers/tempfile.py index 6995be1db98..70cc688156a 100644 --- a/pygmt/helpers/tempfile.py +++ b/pygmt/helpers/tempfile.py @@ -1,3 +1,4 @@ +# noqa: A005 """ Utilities for dealing with temporary file management. """ diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index b53942818c5..e32f5bbe03f 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -574,9 +574,8 @@ def launch_external_viewer(fname: str, waiting: float = 0) -> None: } match sys.platform: - case name if ( - (name == "linux" or name.startswith("freebsd")) - and (xdgopen := shutil.which("xdg-open")) + case name if (name == "linux" or name.startswith("freebsd")) and ( + xdgopen := shutil.which("xdg-open") ): # Linux/FreeBSD subprocess.run([xdgopen, fname], check=False, **run_args) # type:ignore[call-overload] case "darwin": # macOS diff --git a/pygmt/io.py b/pygmt/io.py index 9451de36c8f..a4ba289c7d9 100644 --- a/pygmt/io.py +++ b/pygmt/io.py @@ -1,3 +1,4 @@ +# noqa: A005 """ PyGMT input/output (I/O) utilities. """ diff --git a/pygmt/src/grd2xyz.py b/pygmt/src/grd2xyz.py index a44dc996c6d..b31d0013a25 100644 --- a/pygmt/src/grd2xyz.py +++ b/pygmt/src/grd2xyz.py @@ -145,8 +145,7 @@ def grd2xyz( if kwargs.get("o") is not None and output_type == "pandas": msg = ( - "If 'outcols' is specified, 'output_type' must be either 'numpy' " - "or 'file'." + "If 'outcols' is specified, 'output_type' must be either 'numpy' or 'file'." ) raise GMTInvalidInput(msg) # Set the default column names for the pandas DataFrame header. diff --git a/pygmt/src/select.py b/pygmt/src/select.py index ecd6d12bfad..a7db421a210 100644 --- a/pygmt/src/select.py +++ b/pygmt/src/select.py @@ -1,3 +1,4 @@ +# noqa: A005 """ select - Select data table subsets based on multiple spatial criteria. """ diff --git a/pygmt/tests/baseline/test_plot_datetime.png.dvc b/pygmt/tests/baseline/test_plot_datetime.png.dvc index 714104995ba..1450b29ef82 100644 --- a/pygmt/tests/baseline/test_plot_datetime.png.dvc +++ b/pygmt/tests/baseline/test_plot_datetime.png.dvc @@ -1,5 +1,5 @@ outs: -- md5: 583947facaa873122f0bf18137809cd4 - size: 12695 +- md5: 0a2eae0da1e3d5b71d7392de1c081346 + size: 13124 path: test_plot_datetime.png hash: md5 diff --git a/pygmt/tests/test_clib_to_numpy.py b/pygmt/tests/test_clib_to_numpy.py index 31b6c2421e8..40b45e466d8 100644 --- a/pygmt/tests/test_clib_to_numpy.py +++ b/pygmt/tests/test_clib_to_numpy.py @@ -2,8 +2,8 @@ Tests for the _to_numpy function in the clib.conversion module. """ +import datetime import sys -from datetime import date, datetime import numpy as np import numpy.testing as npt @@ -80,6 +80,70 @@ def test_to_numpy_python_types(data, expected_dtype): npt.assert_array_equal(result, data) +@pytest.mark.parametrize( + "data", + [ + pytest.param( + ["2018", "2018-02", "2018-03-01", "2018-04-01T01:02:03"], id="iso8601" + ), + pytest.param( + [ + datetime.date(2018, 1, 1), + datetime.datetime(2018, 2, 1), + datetime.date(2018, 3, 1), + datetime.datetime(2018, 4, 1, 1, 2, 3), + ], + id="datetime", + ), + pytest.param( + [ + np.datetime64("2018"), + np.datetime64("2018-02"), + np.datetime64("2018-03-01"), + np.datetime64("2018-04-01T01:02:03"), + ], + id="np_datetime64", + ), + pytest.param( + [ + pd.Timestamp("2018-01-01"), + pd.Timestamp("2018-02-01"), + pd.Timestamp("2018-03-01"), + pd.Timestamp("2018-04-01T01:02:03"), + ], + id="pd_timestamp", + ), + pytest.param( + [ + "2018-01-01", + np.datetime64("2018-02-01"), + datetime.datetime(2018, 3, 1), + pd.Timestamp("2018-04-01T01:02:03"), + ], + id="mixed", + ), + ], +) +def test_to_numpy_python_datetime(data): + """ + Test the _to_numpy function with Python sequence of datetime types. + """ + result = _to_numpy(data) + assert result.dtype.type == np.datetime64 + npt.assert_array_equal( + result, + np.array( + [ + "2018-01-01T00:00:00", + "2018-02-01T00:00:00", + "2018-03-01T00:00:00", + "2018-04-01T01:02:03", + ], + dtype="datetime64[s]", + ), + ) + + ######################################################################################## # Test the _to_numpy function with NumPy arrays. # @@ -603,9 +667,9 @@ def test_to_numpy_pyarrow_date(dtype, expected_dtype): Here we explicitly check the dtype and date unit of the result. """ data = [ - date(2024, 1, 1), - datetime(2024, 1, 2), - datetime(2024, 1, 3), + datetime.date(2024, 1, 1), + datetime.datetime(2024, 1, 2), + datetime.datetime(2024, 1, 3), ] array = pa.array(data, type=dtype) result = _to_numpy(array) @@ -649,7 +713,10 @@ def test_to_numpy_pyarrow_timestamp(dtype, expected_dtype): Reference: https://arrow.apache.org/docs/python/generated/pyarrow.timestamp.html """ - data = [datetime(2024, 1, 2, 3, 4, 5), datetime(2024, 1, 2, 3, 4, 6)] + data = [ + datetime.datetime(2024, 1, 2, 3, 4, 5), + datetime.datetime(2024, 1, 2, 3, 4, 6), + ] array = pa.array(data, type=dtype) result = _to_numpy(array) _check_result(result, np.datetime64) diff --git a/pygmt/tests/test_clib_virtualfile_from_stringio.py b/pygmt/tests/test_clib_virtualfile_from_stringio.py index ce6de238a88..62daaa688c8 100644 --- a/pygmt/tests/test_clib_virtualfile_from_stringio.py +++ b/pygmt/tests/test_clib_virtualfile_from_stringio.py @@ -43,14 +43,9 @@ def test_virtualfile_from_stringio(): Test the virtualfile_from_stringio method. """ data = io.StringIO( - "# Comment\n" - "H 24p Legend\n" - "N 2\n" - "S 0.1i c 0.15i p300/12 0.25p 0.3i My circle\n" - ) - expected = ( - ">\n" "H 24p Legend\n" "N 2\n" "S 0.1i c 0.15i p300/12 0.25p 0.3i My circle\n" + "# Comment\nH 24p Legend\nN 2\nS 0.1i c 0.15i p300/12 0.25p 0.3i My circle\n" ) + expected = ">\nH 24p Legend\nN 2\nS 0.1i c 0.15i p300/12 0.25p 0.3i My circle\n" assert _stringio_to_dataset(data) == expected @@ -66,13 +61,7 @@ def test_one_segment(): "6 7 8 9 FGHIJK LMN OPQ\n" "RSTUVWXYZ\n" ) - expected = ( - "> Segment 1\n" - "1 2 3 ABC\n" - "4 5 DE\n" - "6 7 8 9 FGHIJK LMN OPQ\n" - "RSTUVWXYZ\n" - ) + expected = "> Segment 1\n1 2 3 ABC\n4 5 DE\n6 7 8 9 FGHIJK LMN OPQ\nRSTUVWXYZ\n" assert _stringio_to_dataset(data) == expected diff --git a/pygmt/tests/test_grdview.py b/pygmt/tests/test_grdview.py index f73b1150e54..3be4ed7aa42 100644 --- a/pygmt/tests/test_grdview.py +++ b/pygmt/tests/test_grdview.py @@ -161,7 +161,7 @@ def test_grdview_with_perspective_and_zaxis_frame(xrgrid, region): a Transverse Mercator (T) projection. """ fig = Figure() - projection = f"T{(region[0]+region[1])/2}/{abs((region[2]+region[3])/2)}" + projection = f"T{(region[0] + region[1]) / 2}/{abs((region[2] + region[3]) / 2)}" fig.grdview( grid=xrgrid, projection=projection, diff --git a/pygmt/tests/test_info.py b/pygmt/tests/test_info.py index 3ac9f27c4e1..d055abb61ec 100644 --- a/pygmt/tests/test_info.py +++ b/pygmt/tests/test_info.py @@ -23,10 +23,7 @@ def test_info(): """ output = info(data=POINTS_DATA) expected_output = ( - f"{POINTS_DATA}: N = 20 " - "<11.5309/61.7074> " - "<-2.9289/7.8648> " - "<0.1412/0.9338>\n" + f"{POINTS_DATA}: N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n" ) assert output == expected_output @@ -57,10 +54,7 @@ def test_info_path(table): """ output = info(data=table) expected_output = ( - f"{POINTS_DATA}: N = 20 " - "<11.5309/61.7074> " - "<-2.9289/7.8648> " - "<0.1412/0.9338>\n" + f"{POINTS_DATA}: N = 20 <11.5309/61.7074> <-2.9289/7.8648> <0.1412/0.9338>\n" ) assert output == expected_output diff --git a/pygmt/tests/test_plot.py b/pygmt/tests/test_plot.py index 721b7841307..c2f2b846724 100644 --- a/pygmt/tests/test_plot.py +++ b/pygmt/tests/test_plot.py @@ -467,9 +467,14 @@ def test_plot_datetime(): fig.plot(x=x, y=y, style="a0.2c", pen="1p") # the Python built-in datetime and date - x = [datetime.date(2018, 1, 1), datetime.datetime(2019, 1, 1)] + x = [datetime.date(2018, 1, 1), datetime.datetime(2019, 1, 1, 0, 0, 0)] y = [8.5, 9.5] fig.plot(x=x, y=y, style="i0.2c", pen="1p") + + # Python sequence of pd.Timestamp + x = [pd.Timestamp("2018-01-01"), pd.Timestamp("2019-01-01")] + y = [5.5, 6.5] + fig.plot(x=x, y=y, style="d0.2c", pen="1p") return fig