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