From bb073efb755aa7cc0ad497c0a0662ce25165645f Mon Sep 17 00:00:00 2001 From: Mike Taves Date: Fri, 15 Nov 2024 10:02:39 +1300 Subject: [PATCH] chore: add codespell configuration and check with lint GHA --- .github/workflows/commit.yml | 3 +++ DEVELOPER.md | 4 ++-- autotest/test_gridgen.py | 2 +- autotest/test_mbase.py | 2 +- autotest/test_modflow.py | 4 ++-- autotest/test_uzf.py | 8 +++---- flopy/discretization/unstructuredgrid.py | 6 +++--- flopy/discretization/vertexgrid.py | 2 +- flopy/mf6/data/mfdatautil.py | 2 +- flopy/mf6/utils/lakpak_utils.py | 2 +- flopy/modpath/mp6bas.py | 2 +- flopy/plot/crosssection.py | 4 ++-- flopy/plot/map.py | 2 +- flopy/utils/lgrutil.py | 4 ++-- flopy/utils/optionblock.py | 8 +++---- pyproject.toml | 27 ++++++++++++++++++++++++ 16 files changed, 56 insertions(+), 26 deletions(-) diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 64eab8078d..1731c28ede 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -70,6 +70,9 @@ jobs: - name: Check format run: ruff format . --check + - name: Check spelling + run: codespell + - name: Check CITATION.cff run: | cffconvert --validate diff --git a/DEVELOPER.md b/DEVELOPER.md index eebaf78d57..9e007a4989 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -215,7 +215,7 @@ The `section` attribute assigns the example to a group within the rendered docum **Note**: Examples are rendered into a thumbnail gallery view by [nbsphinx](https://github.com/spatialaudio/nbsphinx) when the [online documentation](https://flopy.readthedocs.io/en/latest/) is built. At least one plot/visualization is recommended in order to provide a thumbnail for each example notebook in the [Examples gallery](https://flopy.readthedocs.io/en/latest/notebooks.html)gallery. -**Note**: Thumbnails for the examples gallery are generated automatically from the notebook header (typically the first line, begining with a single '#'), and by default, the last plot generated. Thumbnails can be customized to use any plot in the notebook, or an external image, as described [here](https://nbsphinx.readthedocs.io/en/0.9.1/subdir/gallery.html). +**Note**: Thumbnails for the examples gallery are generated automatically from the notebook header (typically the first line, beginning with a single '#'), and by default, the last plot generated. Thumbnails can be customized to use any plot in the notebook, or an external image, as described [here](https://nbsphinx.readthedocs.io/en/0.9.1/subdir/gallery.html). Each example should create and (attempt to) dispose of its own isolated temporary workspace. On Windows, Python's `TemporaryDirectory` can raise permissions errors, so cleanup is trapped with `try/except`. Some scripts also accept a `--quiet` flag, curtailing verbose output, and a `--keep` option to specify a working directory of the user's choice. @@ -283,7 +283,7 @@ This should complete in under a minute on most machines. Smoke testing aims to c ### Writing tests -Test functions and files should be named informatively, with related tests grouped in the same file. The test suite runs on GitHub Actions in parallel, so tests should not access the working space of other tests, example scripts, tutorials or notebooks. A number of shared test fixtures are [imported](conftest.py) from [`modflow-devtools`](https://github.com/MODFLOW-USGS/modflow-devtools). These include keepable temporary directory fixtures and miscellanous utilities (see `modflow-devtools` repository README for more information on fixture usage). New tests should use these facilities where possible. See also the [contribution guidelines](CONTRIBUTING.md) before submitting a pull request. +Test functions and files should be named informatively, with related tests grouped in the same file. The test suite runs on GitHub Actions in parallel, so tests should not access the working space of other tests, example scripts, tutorials or notebooks. A number of shared test fixtures are [imported](conftest.py) from [`modflow-devtools`](https://github.com/MODFLOW-USGS/modflow-devtools). These include keepable temporary directory fixtures and miscellaneous utilities (see `modflow-devtools` repository README for more information on fixture usage). New tests should use these facilities where possible. See also the [contribution guidelines](CONTRIBUTING.md) before submitting a pull request. ### Debugging tests diff --git a/autotest/test_gridgen.py b/autotest/test_gridgen.py index fbd7d8ad74..6fd8b8d668 100644 --- a/autotest/test_gridgen.py +++ b/autotest/test_gridgen.py @@ -714,7 +714,7 @@ def test_gridgen(function_tmpdir): g6.add_refinement_features(rfpoly, "polygon", 3, range(nlay)) gu.add_refinement_features(rfpoly, "polygon", 3, range(nlay)) - # inactivate parts of mfusg layer 2 to test vertical-pass-through option + # deactivate parts of mfusg layer 2 to test vertical-pass-through option xmin = 0 * delr xmax = 18 * delr ymin = 0 * delc diff --git a/autotest/test_mbase.py b/autotest/test_mbase.py index 2b494bdb31..59e796b057 100644 --- a/autotest/test_mbase.py +++ b/autotest/test_mbase.py @@ -65,7 +65,7 @@ def test_resolve_exe_by_rel_path(function_tmpdir, use_ext, forgive): assert actual.lower() == expected assert which(actual) - # check behavior if exe DNE + # check behavior if exe does not exist with pytest.warns(UserWarning) if forgive else pytest.raises(FileNotFoundError): assert not resolve_exe("../bin/mf2005", forgive) diff --git a/autotest/test_modflow.py b/autotest/test_modflow.py index c2e955633d..696b7835ea 100644 --- a/autotest/test_modflow.py +++ b/autotest/test_modflow.py @@ -277,14 +277,14 @@ def test_exe_selection(example_data_path, function_tmpdir): == exe_name ) - # init/load should warn if exe DNE + # init/load should warn if exe does not exist exe_name = "not_an_exe" with pytest.warns(UserWarning): ml = Modflow(exe_name=exe_name) with pytest.warns(UserWarning): ml = Modflow.load(namfile_path, exe_name=exe_name, model_ws=model_path) - # run should error if exe DNE + # run should error if exe does not exist ml = Modflow.load(namfile_path, exe_name=exe_name, model_ws=model_path) ml.change_model_ws(function_tmpdir) ml.write_input() diff --git a/autotest/test_uzf.py b/autotest/test_uzf.py index 9d9873ceb1..4c67830304 100644 --- a/autotest/test_uzf.py +++ b/autotest/test_uzf.py @@ -625,15 +625,15 @@ def test_uzf_negative_iuzfopt(function_tmpdir): def test_optionsblock_auxillary_typo(): - # Incorrect: auxillary + # Incorrect: auxillary # codespell:ignore # Correct: auxiliary options = OptionBlock("", ModflowWel, block=True) assert options.auxiliary == [] with pytest.deprecated_call(): - assert options.auxillary == [] + assert options.auxillary == [] # codespell:ignore with pytest.deprecated_call(): - options.auxillary = ["aux", "iface"] + options.auxillary = ["aux", "iface"] # codespell:ignore assert options.auxiliary == ["aux", "iface"] options.auxiliary = [] with pytest.deprecated_call(): - assert options.auxillary == [] + assert options.auxillary == [] # codespell:ignore diff --git a/flopy/discretization/unstructuredgrid.py b/flopy/discretization/unstructuredgrid.py index 3c24706467..f9ce68e313 100644 --- a/flopy/discretization/unstructuredgrid.py +++ b/flopy/discretization/unstructuredgrid.py @@ -618,12 +618,12 @@ def neighbors(self, node=None, **kwargs): reset = kwargs.pop("reset", False) if method == "iac": if self._neighbors is None or reset: - neighors = {} + neighbors = {} idx0 = 0 for node, ia in enumerate(self._iac): idx1 = idx0 + ia - neighors[node] = list(self._ja[idx0 + 1 : idx1]) - self._neighbors = neighors + neighbors[node] = list(self._ja[idx0 + 1 : idx1]) + self._neighbors = neighbors if node is not None: return self._neighbors[node] else: diff --git a/flopy/discretization/vertexgrid.py b/flopy/discretization/vertexgrid.py index f55d8a306a..7e811f506c 100644 --- a/flopy/discretization/vertexgrid.py +++ b/flopy/discretization/vertexgrid.py @@ -222,7 +222,7 @@ def grid_lines(self): if self.cell1d is not None: close_cell = False - # go through each cell and create a line segement for each face + # go through each cell and create a line segment for each face lines = [] ncpl = len(xgrid) for icpl in range(ncpl): diff --git a/flopy/mf6/data/mfdatautil.py b/flopy/mf6/data/mfdatautil.py index ec244c3fea..45d67913ae 100644 --- a/flopy/mf6/data/mfdatautil.py +++ b/flopy/mf6/data/mfdatautil.py @@ -15,7 +15,7 @@ def iterable(obj, any_iterator=False): if any_iterator: try: my_iter = iter(obj) - except TypeError as te: + except TypeError: return False return True else: diff --git a/flopy/mf6/utils/lakpak_utils.py b/flopy/mf6/utils/lakpak_utils.py index 8b1e1b25b1..94b52a5206 100644 --- a/flopy/mf6/utils/lakpak_utils.py +++ b/flopy/mf6/utils/lakpak_utils.py @@ -40,7 +40,7 @@ def get_lak_connections(modelgrid, lake_map, idomain=None, bedleak=None): Returns ------- idomain : ndarry - idomain adjusted to inactivate cells with lakes + idomain adjusted to deactivate cells with lakes connection_dict : dict dictionary with the zero-based lake number keys and number of connections in a lake values diff --git a/flopy/modpath/mp6bas.py b/flopy/modpath/mp6bas.py index f98ff6a1b3..9a50922d84 100644 --- a/flopy/modpath/mp6bas.py +++ b/flopy/modpath/mp6bas.py @@ -28,7 +28,7 @@ class Modpath6Bas(Package): hdry : float Head value assigned to dry cells (default is -8888.). def_face_ct : int - Number fo default iface codes to read (default is 0). + Number of default iface codes to read (default is 0). bud_label : str or list of strs MODFLOW budget item to which a default iface is assigned. def_iface : int or list of ints diff --git a/flopy/plot/crosssection.py b/flopy/plot/crosssection.py index 7229fddb3c..ed916ebde4 100644 --- a/flopy/plot/crosssection.py +++ b/flopy/plot/crosssection.py @@ -185,7 +185,7 @@ def __init__( self.xypts = plotutil.UnstructuredPlotUtilities.filter_line_segments( self.xypts, threshold=min_segment_length ) - # need to ensure that the ordering of verticies in xypts is correct + # need to ensure that the ordering of vertices in xypts is correct # based on the projection. In certain cases vertices need to be sorted # for the specific "projection" for node, points in self.xypts.items(): @@ -933,7 +933,7 @@ def plot_centers( optional numpy nd.array of size modelgrid.nnodes s : None, float, numpy array optional point size parameter - masked_values : None, iteratable + masked_values : None, iterable optional list, tuple, or np array of array (a) values to mask inactive : bool boolean flag to include inactive cell centers in the plot. diff --git a/flopy/plot/map.py b/flopy/plot/map.py index 49a53b38b9..00e39bde4a 100644 --- a/flopy/plot/map.py +++ b/flopy/plot/map.py @@ -629,7 +629,7 @@ def plot_centers( optional numpy nd.array of size modelgrid.nnodes s : None, float, numpy array optional point size parameter - masked_values : None, iteratable + masked_values : None, iterable optional list, tuple, or np array of array (a) values to mask inactive : bool boolean flag to include inactive cell centers in the plot. diff --git a/flopy/utils/lgrutil.py b/flopy/utils/lgrutil.py index 1aab5ddd07..b2edf951d6 100644 --- a/flopy/utils/lgrutil.py +++ b/flopy/utils/lgrutil.py @@ -589,7 +589,7 @@ def to_disv_gridprops(self): used to create a disv grid (instead of a separate parent and child representation). The gridprops dictionary can be unpacked into the flopy.mf6.Modflowdisv() constructor - and flopy.discretization.VertexGrid() contructor. + and flopy.discretization.VertexGrid() constructor. Note that export capability will only work if the parent and child models have corresponding layers. @@ -964,7 +964,7 @@ def get_disv_gridprops(self): used to create a disv grid (instead of a separate parent and child representation). The gridprops dictionary can be unpacked into the flopy.mf6.Modflowdisv() constructor - and flopy.discretization.VertexGrid() contructor. + and flopy.discretization.VertexGrid() constructor. Note that export capability will only work if the parent and child models have corresponding layers. diff --git a/flopy/utils/optionblock.py b/flopy/utils/optionblock.py index 0ebee3949b..5d85ecf0ad 100644 --- a/flopy/utils/optionblock.py +++ b/flopy/utils/optionblock.py @@ -59,10 +59,10 @@ def __init__(self, options_line, package, block=True): self._set_attributes() def __getattr__(self, key): - if key == "auxillary": # catch typo from older version + if key == "auxillary": # catch typo from older version - codespell:ignore key = "auxiliary" warnings.warn( - "the atttribute 'auxillary' is deprecated, use 'auxiliary' instead", + "the attribute 'auxillary' is deprecated, use 'auxiliary' instead", category=DeprecationWarning, ) return super().__getattribute__(key) @@ -159,10 +159,10 @@ def __setattr__(self, key, value): is consistent with the attribute data type """ - if key == "auxillary": # catch typo from older version + if key == "auxillary": # catch typo from older version - codespell:ignore key = "auxiliary" warnings.warn( - "the atttribute 'auxillary' is deprecated, use 'auxiliary' instead", + "the attribute 'auxillary' is deprecated, use 'auxiliary' instead", category=DeprecationWarning, ) diff --git a/pyproject.toml b/pyproject.toml index f1f174bab8..93412784e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,8 @@ dynamic = ["version", "readme"] dev = ["flopy[lint,test,optional,doc]"] lint = [ "cffconvert", + "codespell", + "tomli ; python_version <'3.11'", "ruff" ] test = [ @@ -159,3 +161,28 @@ ignore = [ [tool.ruff.lint.per-file-ignores] ".docs/**/*.py" = ["E501"] "flopy/mf6/**/*.py" = ["E501", "ISC001"] + +[tool.codespell] +skip = "cliff.toml,./examples/data/*" +ignore-words-list = [ + "alltime", + "dum", + "inout", + "intot", + "delt", + "gage", + "gages", + "datbase", + "wel", + "nam", + "lke", + "ist", + "ninj", + "drob", + "thck", + "vor", + "yur", + "localy", + "vertx", + "nd", +]