diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 39c8cce595c..da451553c82 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -61,7 +61,7 @@ jobs: echo $CONDA/bin >> $GITHUB_PATH conda install --solver=libmamba gmt=6.4.0 python=3.12 \ numpy pandas xarray netCDF4 packaging \ - geopandas pytest pytest-benchmark pytest-mpl + geopandas pytest pytest-mpl python -m pip install -U pytest-codspeed setuptools # Download cached remote files (artifacts) from GitHub diff --git a/.github/workflows/cache_data.yaml b/.github/workflows/cache_data.yaml index 998158789b5..3a4a43852c3 100644 --- a/.github/workflows/cache_data.yaml +++ b/.github/workflows/cache_data.yaml @@ -1,18 +1,21 @@ -# Cache GMT remote data files and uploads as artifacts +# Cache GMT remote data files and upload as artifacts # # This workflow downloads data files needed by PyGMT tests/documentation from # the GMT data server and uploads as workflow artifacts which can be accessed # by other GitHub Actions workflows. # # It is scheduled to run every Sunday at 12:00 (UTC). If new remote files are -# needed urgently, maintainers can manually uncomment the 'pull_request:' line -# below to refresh the cache. +# needed urgently, maintainers can update the workflow file or +# 'pygmt/helpers/caching.py' file to refresh the cache. # name: Cache data on: - # Uncomment the 'pull_request' line below to manually re-cache data artifacts - # pull_request: + pull_request: + # Make any changes to the following files to refresh the cache + paths: + - 'pygmt/helpers/caching.py' + - '.github/workflows/cache_data.yaml' # Schedule runs on 12 noon every Sunday schedule: - cron: '0 12 * * 0' @@ -61,7 +64,7 @@ jobs: # Download remote files - name: Download remote data run: | - python -c "from pygmt.helpers.testing import download_test_data; download_test_data()" + python -c "from pygmt.helpers.caching import cache_data; cache_data()" # Upload the downloaded files as artifacts to GitHub - name: Upload artifacts to GitHub diff --git a/.github/workflows/ci_docs.yml b/.github/workflows/ci_docs.yml index bf732b5f0e8..759410a763d 100644 --- a/.github/workflows/ci_docs.yml +++ b/.github/workflows/ci_docs.yml @@ -72,7 +72,7 @@ jobs: channels: - conda-forge - nodefaults - cache-downloads: true + cache-downloads: false cache-environment: true create-args: >- python=3.12 diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index b31128ad1ec..f68d4d355b3 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -101,7 +101,7 @@ jobs: channels: - conda-forge - nodefaults - cache-downloads: true + cache-downloads: false cache-environment: true create-args: >- python=${{ matrix.python-version }}${{ matrix.optional-packages }} diff --git a/.github/workflows/ci_tests_dev.yaml b/.github/workflows/ci_tests_dev.yaml index 348d9331c34..b518eb90acd 100644 --- a/.github/workflows/ci_tests_dev.yaml +++ b/.github/workflows/ci_tests_dev.yaml @@ -86,7 +86,7 @@ jobs: channels: - conda-forge - nodefaults - cache-downloads: true + cache-downloads: false cache-environment: true create-args: >- python=3.12 diff --git a/.github/workflows/ci_tests_legacy.yaml b/.github/workflows/ci_tests_legacy.yaml index 81449848ed0..ac1361c8baf 100644 --- a/.github/workflows/ci_tests_legacy.yaml +++ b/.github/workflows/ci_tests_legacy.yaml @@ -59,7 +59,7 @@ jobs: channels: - conda-forge - nodefaults - cache-downloads: true + cache-downloads: false cache-environment: true create-args: >- python=3.9 diff --git a/.github/workflows/format-command.yml b/.github/workflows/format-command.yml index 2bdbb18c37e..5e31c483627 100644 --- a/.github/workflows/format-command.yml +++ b/.github/workflows/format-command.yml @@ -25,7 +25,7 @@ jobs: # Install formatting tools - name: Install formatting tools run: | - python -m pip install docformatter ruff + python -m pip install ruff python -m pip list sudo apt-get install dos2unix diff --git a/.github/workflows/style_checks.yaml b/.github/workflows/style_checks.yaml index bab24f9c1f5..16b376455f9 100644 --- a/.github/workflows/style_checks.yaml +++ b/.github/workflows/style_checks.yaml @@ -34,11 +34,11 @@ jobs: - name: Install packages run: | - python -m pip install docformatter ruff + python -m pip install ruff python -m pip list sudo apt-get install dos2unix - - name: Formatting check (docformatter, ruff) + - name: Formatting check (ruff) run: make check - name: Ensure files use UNIX line breaks and have 644 permission diff --git a/Makefile b/Makefile index 490797339a5..c3d59ce6848 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,8 @@ help: @echo " fulltest run the test suite (including all doctests)" @echo " doctest run the doctests only" @echo " test_no_images run the test suite (including all doctests) but skip image comparisons" - @echo " format run docformatter and ruff to automatically format the code" - @echo " check run code style and quality checks (docformatter and ruff)" + @echo " format run ruff to automatically format the code" + @echo " check run ruff to check code style and quality" @echo " codespell run codespell to check common misspellings" @echo " typecheck run mypy for static type check" @echo " clean clean up build and generated files" @@ -60,12 +60,10 @@ test_no_images: PYTEST_ARGS=-o addopts="--verbose --durations=0 --durations-min= test_no_images: _runtest format: - docformatter --in-place $(FORMAT_FILES) ruff check --fix $(FORMAT_FILES) ruff format $(FORMAT_FILES) check: - docformatter --check $(FORMAT_FILES) ruff check $(FORMAT_FILES) ruff format --check $(FORMAT_FILES) diff --git a/doc/contributing.md b/doc/contributing.md index 5f560cca83e..ee58f8945c3 100644 --- a/doc/contributing.md +++ b/doc/contributing.md @@ -406,7 +406,7 @@ arguments and return values. While the maximum line length for code is automatically set by ruff, docstrings must be formatted manually. To play nicely with Jupyter and IPython, **keep docstrings -limited to 79 characters** per line. +limited to 88 characters** per line. ### Standards for Example Code @@ -471,14 +471,10 @@ code, be sure to follow the general guidelines in the ### Code Style -We use some tools to format the code so we don't have to think about it: - -- [docformatter](https://github.com/myint/docformatter) -- [ruff](https://docs.astral.sh/ruff) - -These tools loosely follow the [PEP8](http://pep8.org) guide but with a few -differences. Regardless, you won't have to worry about formatting the code yourself. -Before committing, run it to automatically format your code: +We use the [ruff](https://docs.astral.sh/ruff) tool to format the code, so we +don't have to think about it. It loosely follow the [PEP8](http://pep8.org) guide +but with a few differences. Regardless, you won't have to worry about formatting +the code yourself. Before committing, run it to automatically format your code: ```bash make format @@ -511,7 +507,7 @@ The [`Makefile`](https://github.com/GenericMappingTools/pygmt/blob/main/Makefile contains rules for running the linter checks: ```bash -make check # Runs docformatter and ruff (in check mode) +make check # Runs ruff in check mode ``` ### Testing your Code diff --git a/environment.yml b/environment.yml index dc40f3cf84e..de6870344bd 100644 --- a/environment.yml +++ b/environment.yml @@ -24,7 +24,6 @@ dependencies: - pip # Dev dependencies (style checks) - codespell - - docformatter>=1.7.2 - ruff>=0.1.9 # Dev dependencies (unit testing) - matplotlib diff --git a/examples/gallery/3d_plots/grdview_surface.py b/examples/gallery/3d_plots/grdview_surface.py index 97af6115e49..beec0eb6c4b 100644 --- a/examples/gallery/3d_plots/grdview_surface.py +++ b/examples/gallery/3d_plots/grdview_surface.py @@ -23,6 +23,9 @@ # Define an interesting function of two variables, see: # https://en.wikipedia.org/wiki/Ackley_function def ackley(x, y): + """ + Ackley function. + """ return ( -20 * np.exp(-0.2 * np.sqrt(0.5 * (x**2 + y**2))) - np.exp(0.5 * (np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y))) diff --git a/examples/gallery/lines/vector_styles.py b/examples/gallery/lines/vector_styles.py index e3a13cdd5ee..726bfabd642 100644 --- a/examples/gallery/lines/vector_styles.py +++ b/examples/gallery/lines/vector_styles.py @@ -4,9 +4,7 @@ The :meth:`pygmt.Figure.plot` method can plot Cartesian, circular, and geographic vectors. The ``style`` parameter controls vector attributes. -See also -:doc:`Vector attributes example `. - +See also :doc:`Vector attributes example `. """ # %% diff --git a/examples/tutorials/advanced/working_with_panel.py b/examples/tutorials/advanced/working_with_panel.py index 83d31e2a355..cf0786c3b5e 100644 --- a/examples/tutorials/advanced/working_with_panel.py +++ b/examples/tutorials/advanced/working_with_panel.py @@ -73,9 +73,11 @@ ) -# Define a function for plotting the single slices @pn.depends(central_lon=slider_lon) def view(central_lon): + """ + Define a function for plotting the single slices. + """ # Create a new instance or object of the pygmt.Figure() class fig = pygmt.Figure() fig.coast( @@ -112,9 +114,11 @@ def view(central_lon): ) -# Define a function for plotting the single slices @pn.depends(central_lon=slider_lon) def view(central_lon): + """ + Define a function for plotting the single slices. + """ # Create a new instance or object of the pygmt.Figure() class fig = pygmt.Figure() # Set up a colormap for the elevation in meters diff --git a/pygmt/figure.py b/pygmt/figure.py index bcb5a84835c..587ce0fa4d9 100644 --- a/pygmt/figure.py +++ b/pygmt/figure.py @@ -88,7 +88,9 @@ def __init__(self): self._activate_figure() def __del__(self): - # Clean up the temporary directory that stores the previews + """ + Clean up the temporary directory that stores the previews. + """ if hasattr(self, "_preview_dir"): self._preview_dir.cleanup() diff --git a/pygmt/helpers/caching.py b/pygmt/helpers/caching.py new file mode 100644 index 00000000000..e0786053e9f --- /dev/null +++ b/pygmt/helpers/caching.py @@ -0,0 +1,87 @@ +""" +Functions for download remote data files as cache. +""" +from pygmt.src import which + + +def cache_data(): + """ + Download GMT remote data files used in PyGMT tests and docs as cache files. + """ + # List of datasets to download + datasets = [ + # Earth relief grids + "@earth_gebco_01d_g", + "@earth_gebcosi_01d_g", + "@earth_gebcosi_15m_p", + "@earth_relief_01d_p", + "@earth_relief_01d_g", + "@earth_relief_30m_p", + "@earth_relief_30m_g", + "@earth_relief_10m_p", + "@earth_relief_10m_g", + "@earth_relief_05m_p", + "@earth_relief_05m_g", + "@earth_synbath_01d_g", + # List of tiles of 03s srtm data. + # Names like @N35E135.earth_relief_03s_g.nc are for internal use only. + # The naming scheme may change. DO NOT USE IT IN YOUR SCRIPTS. + "@N30W120.earth_relief_15s_p.nc", + "@N35E135.earth_relief_03s_g.nc", + "@N37W120.earth_relief_03s_g.nc", + "@N00W090.earth_relief_03m_p.nc", + "@N00E135.earth_relief_30s_g.nc", + "@N00W010.earth_relief_15s_p.nc", # Specific grid for 15s test + "@N04W010.earth_relief_03s_g.nc", # Specific grid for 03s test + # Earth synbath relief grid + "@S15W105.earth_synbath_30s_p.nc", + # Earth seafloor age grids + "@earth_age_01d_g", + "@N00W030.earth_age_01m_g.nc", # Specific grid for 01m test + # Earth geoid grids + "@earth_geoid_01d_g", + "@N00W030.earth_geoid_01m_g.nc", # Specific grid for 01m test + # Earth magnetic anomaly grids + "@earth_mag_01d_g", + "@S30W060.earth_mag_02m_p.nc", # Specific grid for 02m test + "@earth_mag4km_01d_g", + "@S30W120.earth_mag4km_02m_p.nc", # Specific grid for 02m test + # Earth mask grid + "@earth_mask_01d_g", + # Earth free-air anomaly grids + "@earth_faa_01d_g", + "@N00W030.earth_faa_01m_p.nc", # Specific grid for 01m test + # Earth vertical gravity gradient grids + "@earth_vgg_01d_g", + "@N00W030.earth_vgg_01m_p.nc", # Specific grid for 01m test + # Earth WDMAM grids + "@earth_wdmam_01d_g", + "@S90E000.earth_wdmam_03m_g.nc", # Specific grid for 03m test + # Earth day/night grids + "@earth_day_01d_p", + # Other cache files + "@capitals.gmt", + "@circuit.png", + "@earth_relief_20m_holes.grd", + "@EGM96_to_36.txt", + "@MaunaLoa_CO2.txt", + "@RidgeTest.shp", + "@RidgeTest.shx", + "@RidgeTest.dbf", + "@RidgeTest.prj", + "@Table_5_11.txt", + "@Table_5_11_mean.xyz", + "@fractures_06.txt", + "@hotspots.txt", + "@ridge.txt", + "@mars370d.txt", + "@srtm_tiles.nc", # needed for 03s and 01s relief data + "@static_earth_relief.nc", + "@ternary.txt", + "@test.dat.nc", + "@tut_bathy.nc", + "@tut_quakes.ngdc", + "@tut_ship.xyz", + "@usgs_quakes_22.txt", + ] + which(fname=datasets, download="a") diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py index 2db4784fcca..57bd0f90014 100644 --- a/pygmt/helpers/decorators.py +++ b/pygmt/helpers/decorators.py @@ -445,7 +445,7 @@ def fmt_docstring(module_func): - J = projection - R = region - """ + """ # noqa: D410,D411 filler_text = {} if hasattr(module_func, "aliases"): diff --git a/pygmt/helpers/tempfile.py b/pygmt/helpers/tempfile.py index 7226e1b0d95..5545d2b3695 100644 --- a/pygmt/helpers/tempfile.py +++ b/pygmt/helpers/tempfile.py @@ -62,9 +62,15 @@ def __init__(self, prefix="pygmt-", suffix=".txt"): self.name = tmpfile.name def __enter__(self): + """ + Do nothing but return the object. + """ return self def __exit__(self, *args): + """ + Remove the temporary file. + """ if os.path.exists(self.name): os.remove(self.name) diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 6a9fbec5e17..81ffc2ff5cf 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -142,89 +142,6 @@ def wrapper(*args, ext="png", request=None, **kwargs): return decorator -def download_test_data(): - """ - Convenience function to download remote data files used in PyGMT tests and docs. - """ - # List of datasets to download - datasets = [ - # Earth relief grids - "@earth_gebco_01d_g", - "@earth_gebcosi_01d_g", - "@earth_gebcosi_15m_p", - "@earth_relief_01d_p", - "@earth_relief_01d_g", - "@earth_relief_30m_p", - "@earth_relief_30m_g", - "@earth_relief_10m_p", - "@earth_relief_10m_g", - "@earth_relief_05m_p", - "@earth_relief_05m_g", - "@earth_synbath_01d_g", - # List of tiles of 03s srtm data. - # Names like @N35E135.earth_relief_03s_g.nc is for internal use only. - # The naming scheme may change. DO NOT USE IT IN YOUR SCRIPTS. - "@N30W120.earth_relief_15s_p.nc", - "@N35E135.earth_relief_03s_g.nc", - "@N37W120.earth_relief_03s_g.nc", - "@N00W090.earth_relief_03m_p.nc", - "@N00E135.earth_relief_30s_g.nc", - "@N00W010.earth_relief_15s_p.nc", # Specific grid for 15s test - "@N04W010.earth_relief_03s_g.nc", # Specific grid for 03s test - # Earth synbath relief grids - "@S15W105.earth_synbath_30s_p.nc", - # Earth seafloor age grids - "@earth_age_01d_g", - "@N00W030.earth_age_01m_g.nc", # Specific grid for 01m test - # Earth geoid grids - "@earth_geoid_01d_g", - "@N00W030.earth_geoid_01m_g.nc", # Specific grid for 01m test - # Earth magnetic anomaly grids - "@earth_mag_01d_g", - "@S30W060.earth_mag_02m_p.nc", # Specific grid for 02m test - "@earth_mag4km_01d_g", - "@S30W120.earth_mag4km_02m_p.nc", # Specific grid for 02m test - # Earth mask grid - "@earth_mask_01d_g", - # Earth free-air anomaly grids - "@earth_faa_01d_g", - "@N00W030.earth_faa_01m_p.nc", # Specific grid for 01m test - # Earth vertical gravity gradient grids - "@earth_vgg_01d_g", - "@N00W030.earth_vgg_01m_p.nc", # Specific grid for 01m test - # Earth WDMAM grids - "@earth_wdmam_01d_g", - "@S90E000.earth_wdmam_03m_g.nc", # Specific grid for 03m test - # Earth day/night grids - "@earth_day_01d_p", - # Other cache files - "@capitals.gmt", - "@circuit.png", - "@earth_relief_20m_holes.grd", - "@EGM96_to_36.txt", - "@MaunaLoa_CO2.txt", - "@RidgeTest.shp", - "@RidgeTest.shx", - "@RidgeTest.dbf", - "@RidgeTest.prj", - "@Table_5_11.txt", - "@Table_5_11_mean.xyz", - "@fractures_06.txt", - "@hotspots.txt", - "@ridge.txt", - "@mars370d.txt", - "@srtm_tiles.nc", # needed for 03s and 01s relief data - "@static_earth_relief.nc", - "@ternary.txt", - "@test.dat.nc", - "@tut_bathy.nc", - "@tut_quakes.ngdc", - "@tut_ship.xyz", - "@usgs_quakes_22.txt", - ] - which(fname=datasets, download="a") - - def load_static_earth_relief(): """ Load the static_earth_relief file for internal testing. diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index c814ce99f99..0e7bb93f71d 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -529,7 +529,7 @@ def args_in_kwargs(args, kwargs): short-form aliases of the parameters. Returns - -------- + ------- bool If one of the required arguments is in ``kwargs``. diff --git a/pygmt/src/config.py b/pygmt/src/config.py index c684b745e77..dd0854a296b 100644 --- a/pygmt/src/config.py +++ b/pygmt/src/config.py @@ -203,10 +203,15 @@ def __init__(self, **kwargs): lib.call_module(module="set", args=arg_str) def __enter__(self): + """ + Do nothing but return the object. + """ return self def __exit__(self, exc_type, exc_value, traceback): - # revert to initial values + """ + Revert GMT configurations to initial values. + """ arg_str = " ".join( [f'{key}="{value}"' for key, value in self.old_defaults.items()] ) diff --git a/pygmt/src/grdhisteq.py b/pygmt/src/grdhisteq.py index 97d44048264..c804d8f8f28 100644 --- a/pygmt/src/grdhisteq.py +++ b/pygmt/src/grdhisteq.py @@ -102,7 +102,7 @@ def _grdhisteq(grid, output_type, **kwargs): ``outgrid`` or ``outfile``) See Also - ------- + -------- :func:`pygmt.grd2cpt` """ @@ -194,7 +194,7 @@ def equalize_grid( >>> grid = pygmt.grdhisteq.equalize_grid(grid=grid, gaussian=True) See Also - ------- + -------- :func:`pygmt.grd2cpt` Note @@ -306,7 +306,7 @@ def compute_bins( 4 705.0 2275.5 See Also - ------- + -------- :func:`pygmt.grd2cpt` Note diff --git a/pygmt/src/grdtrack.py b/pygmt/src/grdtrack.py index c8d7a2b0d97..1d0daa1b800 100644 --- a/pygmt/src/grdtrack.py +++ b/pygmt/src/grdtrack.py @@ -209,7 +209,7 @@ def grdtrack(grid, points=None, newcolname=None, outfile=None, **kwargs): - **+c**\ *fact* : Compute envelope on stacked profile as ±\ *fact* \*\ *deviation* [Default fact value is 2]. - Notes: + Here are some notes: 1. Deviations depend on *method* and are st.dev (**a**), L1 scale, i.e., 1.4826 \* median absolute deviation (MAD) (for **m** and diff --git a/pygmt/src/solar.py b/pygmt/src/solar.py index 12ff17ca538..3413214cbd6 100644 --- a/pygmt/src/solar.py +++ b/pygmt/src/solar.py @@ -1,6 +1,10 @@ """ solar - Plot day-night terminators and twilight. """ +from __future__ import annotations + +from typing import Literal + import pandas as pd from pygmt.clib import Session from pygmt.exceptions import GMTInvalidInput @@ -22,13 +26,17 @@ t="transparency", ) @kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence") -def solar(self, terminator="d", terminator_datetime=None, **kwargs): +def solar( + self, + terminator: Literal["astronomical", "civil", "day_night", "nautical"] = "day_night", + terminator_datetime=None, + **kwargs, +): r""" Plot day-light terminators or twilights. - This function plots the day-night terminator. Alternatively, it can plot - the terminators for civil twilight, nautical twilight, or astronomical - twilight. + This function plots the day-night terminator. Alternatively, it can plot the + terminators for civil twilight, nautical twilight, or astronomical twilight. Full option list at :gmt-docs:`solar.html` @@ -36,18 +44,20 @@ def solar(self, terminator="d", terminator_datetime=None, **kwargs): Parameters ---------- - terminator : str - Set the type of terminator displayed. Valid arguments are - ``"day_night"``, ``"civil"``, ``"nautical"``, and ``"astronomical"``, - which can be set with either the full name or the first letter of the - name [Default is ``"day_night"``]. + terminator + Set the type of terminator displayed, which can be set with either the full name + or the first letter of the name. Available options are: - Refer to https://en.wikipedia.org/wiki/Twilight for the definitions of - different types of twilight. + - ``"astronomical"``: Astronomical twilight + - ``"civil"``: Civil twilight + - ``"day_night"``: Day/night terminator + - ``"nautical"``: Nautical twilight + + Refer to https://en.wikipedia.org/wiki/Twilight for the definitions of different + types of twilight. terminator_datetime : str or datetime object - Set the UTC date and time of the displayed terminator - [Default is the current UTC date and time]. It can be - passed as a string or Python datetime object. + Set the UTC date and time of the displayed terminator [Default is the current + UTC date and time]. It can be passed as a string or Python datetime object. {region} {projection} {frame} @@ -86,25 +96,16 @@ def solar(self, terminator="d", terminator_datetime=None, **kwargs): >>> # show the plot >>> fig.show() """ - kwargs = self._preprocess(**kwargs) if kwargs.get("T") is not None: + msg = "Use 'terminator' and 'terminator_datetime' instead of 'T'." + raise GMTInvalidInput(msg) + + valid_terminators = ["day_night", "civil", "nautical", "astronomical"] + if terminator not in valid_terminators and terminator not in "dcna": raise GMTInvalidInput( - "Use 'terminator' and 'terminator_datetime' instead of 'T'." - ) - if terminator not in [ - "day_night", - "civil", - "nautical", - "astronomical", - "d", - "c", - "n", - "a", - ]: - raise GMTInvalidInput( - f"Unrecognized solar terminator type '{terminator}'. Valid values " - "are 'day_night', 'civil', 'nautical', and 'astronomical'." + f"Unrecognized solar terminator type '{terminator}'. " + f"Valid values are {valid_terminators}." ) kwargs["T"] = terminator[0] if terminator_datetime: diff --git a/pygmt/tests/__init__.py b/pygmt/tests/__init__.py index e69de29bb2d..f8ee84678e6 100644 --- a/pygmt/tests/__init__.py +++ b/pygmt/tests/__init__.py @@ -0,0 +1,3 @@ +""" +PyGMT test suite. +""" diff --git a/pygmt/tests/test_clib_loading.py b/pygmt/tests/test_clib_loading.py index 33d1cf2081d..513523917b3 100644 --- a/pygmt/tests/test_clib_loading.py +++ b/pygmt/tests/test_clib_loading.py @@ -24,6 +24,9 @@ def __init__(self, name): self._name = name def __str__(self): + """ + String representation of the object. + """ return self._name diff --git a/pygmt/tests/test_geopandas.py b/pygmt/tests/test_geopandas.py index 589bb7e13af..50d85675730 100644 --- a/pygmt/tests/test_geopandas.py +++ b/pygmt/tests/test_geopandas.py @@ -191,14 +191,15 @@ def test_geopandas_plot_int_dtypes(gdf_ridge, dtype): This is a regression test for https://github.com/GenericMappingTools/pygmt/issues/2497 """ + gdf = gdf_ridge.copy() # Convert NPOINTS column to integer type - gdf_ridge["NPOINTS"] = gdf_ridge.NPOINTS.astype(dtype=dtype) + gdf["NPOINTS"] = gdf.NPOINTS.astype(dtype=dtype) # Plot figure with three polygons colored based on NPOINTS value fig = Figure() makecpt(cmap="lisbon", series=[10, 60, 10], continuous=True) fig.plot( - data=gdf_ridge, + data=gdf, frame=True, pen="1p,black", fill="+z", @@ -215,13 +216,14 @@ def test_geopandas_plot_int64_as_float(gdf_ridge): Check that big 64-bit integers are correctly mapped to float type in geopandas.GeoDataFrame object. """ + gdf = gdf_ridge.copy() factor = 2**32 # Convert NPOINTS column to int64 type and make big integers - gdf_ridge["NPOINTS"] = gdf_ridge.NPOINTS.astype(dtype="int64") - gdf_ridge["NPOINTS"] *= factor + gdf["NPOINTS"] = gdf.NPOINTS.astype(dtype="int64") + gdf["NPOINTS"] *= factor # Make sure the column is bigger than the largest 32-bit integer - assert gdf_ridge["NPOINTS"].abs().max() > 2**31 - 1 + assert gdf["NPOINTS"].abs().max() > 2**31 - 1 # Plot figure with three polygons colored based on NPOINTS value fig = Figure() @@ -229,7 +231,7 @@ def test_geopandas_plot_int64_as_float(gdf_ridge): cmap="lisbon", series=[10 * factor, 60 * factor, 10 * factor], continuous=True ) fig.plot( - data=gdf_ridge, + data=gdf, frame=True, pen="1p,black", fill="+z", diff --git a/pygmt/tests/test_grdimage_image.py b/pygmt/tests/test_grdimage_image.py index 6babb13a587..acb43af0695 100644 --- a/pygmt/tests/test_grdimage_image.py +++ b/pygmt/tests/test_grdimage_image.py @@ -73,7 +73,7 @@ def test_grdimage_image_dataarray_unsupported_dtype(dtype, xr_image): Plot a 3-band RGB image using xarray.DataArray input, with an unsupported data type. """ fig = Figure() - image = xr_image.astype(dtype=dtype) + image = xr_image.copy().astype(dtype=dtype) with pytest.warns(expected_warning=RuntimeWarning) as record: fig.grdimage(grid=image) assert len(record) == 1 diff --git a/pyproject.toml b/pyproject.toml index cf8a3580619..99f50767ae3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,14 +75,6 @@ ignore-words-list = "astroid,oints,reenable,tripel,trough" [tool.coverage.run] omit = ["*/tests/*", "*pygmt/__init__.py"] -[tool.docformatter] -black = true -recursive = true -pre-summary-newline = true -make-summary-multi-line = true -wrap-summaries = 88 -wrap-descriptions = 88 - [tool.mypy] exclude = ["pygmt/tests/"] ignore_missing_imports = true @@ -103,6 +95,7 @@ select = [ "B", # flake8-bugbear "BLE", # flake8-blind-except "C4", # flake8-comprehensions + "D", # pydocstyle "E", # pycodestyle "EXE", # flake8-executable "F", # pyflakes @@ -131,7 +124,17 @@ select = [ "W", # pycodestyle warnings "YTT", # flake8-2020 ] +extend-select = [ + "D213", # Summary lines should be positioned on the second physical line of the docstring. + "D410", # A blank line after section headings. +] ignore = [ + "D200", # One-line docstring should fit on one line + "D202", # No blank lines allowed after function docstring + "D205", # 1 blank line required between summary line and description + "D400", # First line should end with a period + "D401", # First line of docstring should be in imperative mood + "D412", # No blank lines allowed between a section header and its content "E501", # Avoid enforcing line-length violations "ISC001", # Single-line-implicit-string-concatenation, conflict with formatter "PD901", # Allow using the generic variable name `df` for DataFrames @@ -153,6 +156,11 @@ known-third-party = ["pygmt"] [tool.ruff.lint.pycodestyle] max-doc-length = 88 +[tool.ruff.lint.pydocstyle] +# See https://docs.astral.sh/ruff/faq/#does-ruff-support-numpy-or-google-style-docstrings +# for the enabled/disabled rules for the "numpy" convention. +convention = "numpy" + [tool.ruff.lint.pylint] max-args=10