diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 64eab8078..1731c28ed 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 274545047..f40f295af 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -221,7 +221,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. @@ -289,7 +289,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 fbd7d8ad7..6fd8b8d66 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 2b494bdb3..59e796b05 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 c2e955633..696b7835e 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 9d9873ceb..4c6783030 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 3c2470646..f9ce68e31 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 f55d8a306..7e811f506 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 ec244c3fe..45d67913a 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 8b1e1b25b..94b52a520 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 f98ff6a1b..9a50922d8 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 7229fddb3..ed916ebde 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 49a53b38b..00e39bde4 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 1aab5ddd0..b2edf951d 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 0ebee3949..5d85ecf0a 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 f1f174bab..2a4532f31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ dynamic = ["version", "readme"] dev = ["flopy[lint,test,optional,doc]"] lint = [ "cffconvert", + "codespell[toml] >=2.2.2", "ruff" ] test = [ @@ -159,3 +160,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", +]