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

Enable ruff's pydocstyle (D) rules and remove docformatter #2925

Merged
merged 20 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/format-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,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

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/style_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)

Expand Down
16 changes: 6 additions & 10 deletions doc/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:https://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:https://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
Expand Down Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ dependencies:
- pip
# Dev dependencies (style checks)
- codespell
- docformatter>=1.7.2
- ruff>=0.1.9
# Dev dependencies (unit testing)
- matplotlib
Expand Down
3 changes: 3 additions & 0 deletions examples/gallery/3d_plots/grdview_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
4 changes: 1 addition & 3 deletions examples/gallery/lines/vector_styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 </gallery/lines/vector_heads_tails>`.

See also :doc:`Vector attributes example </gallery/lines/vector_heads_tails>`.
"""

# %%
Expand Down
8 changes: 6 additions & 2 deletions examples/tutorials/advanced/working_with_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion pygmt/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
2 changes: 1 addition & 1 deletion pygmt/helpers/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ def fmt_docstring(module_func):
- J = projection
- R = region
<BLANKLINE>
"""
""" # noqa: D410,D411
Copy link
Member

Choose a reason for hiding this comment

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

Since D410 (a blank line after section headings) is enabled in 5d983e6, this noqa: D410, D411 can be removed (and you'll need to run formatting after).

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, this line is required. If removing noqa: D410, D411, the codes will be formatted with the following diff:

diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py
index 57bd0f900..b44dd7fec 100644
--- a/pygmt/helpers/decorators.py
+++ b/pygmt/helpers/decorators.py
@@ -425,6 +425,7 @@ def fmt_docstring(module_func):
     <BLANKLINE>
     My nice module.
     <BLANKLINE>
+
     Parameters
     ----------
     data : str, numpy.ndarray, pandas.DataFrame, xarray.Dataset, or geo...
@@ -445,7 +446,7 @@ def fmt_docstring(module_func):
     - J = projection
     - R = region
     <BLANKLINE>
-    """  # noqa: D410,D411
+    """
     filler_text = {}

     if hasattr(module_func, "aliases"):

Then the doctest fails, because only one blank line is expected, but two blank lines are given (one is <BLANKLINE>, another one is the newly added blank line).

Copy link
Member

@weiji14 weiji14 Jan 4, 2024

Choose a reason for hiding this comment

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

We could just remove the <BLANKLINE> from L427 no? Oh wait, doesn't seem to work, hold on.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, looks like we'll need to keep it, since doctest takes an empty line to mean the end of the expected output according to https://docs.python.org/3/library/doctest.html#how-are-docstring-examples-recognized

filler_text = {}

if hasattr(module_func, "aliases"):
Expand Down
6 changes: 6 additions & 0 deletions pygmt/helpers/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion pygmt/helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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``.

Expand Down
7 changes: 6 additions & 1 deletion pygmt/src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()]
)
Expand Down
6 changes: 3 additions & 3 deletions pygmt/src/grdhisteq.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def _grdhisteq(grid, output_type, **kwargs):
``outgrid`` or ``outfile``)

See Also
-------
--------
:func:`pygmt.grd2cpt`
"""

Expand Down Expand Up @@ -194,7 +194,7 @@ def equalize_grid(
>>> grid = pygmt.grdhisteq.equalize_grid(grid=grid, gaussian=True)

See Also
-------
--------
:func:`pygmt.grd2cpt`

Note
Expand Down Expand Up @@ -306,7 +306,7 @@ def compute_bins(
4 705.0 2275.5

See Also
-------
--------
:func:`pygmt.grd2cpt`

Note
Expand Down
2 changes: 1 addition & 1 deletion pygmt/src/grdtrack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions pygmt/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
PyGMT test suite.
"""
3 changes: 3 additions & 0 deletions pygmt/tests/test_clib_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ def __init__(self, name):
self._name = name

def __str__(self):
"""
String representation of the object.
"""
return self._name


Expand Down
24 changes: 16 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -103,6 +95,7 @@ select = [
"B", # flake8-bugbear
"BLE", # flake8-blind-except
"C4", # flake8-comprehensions
"D", # pydocstyle
"E", # pycodestyle
"EXE", # flake8-executable
"F", # pyflakes
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down