Skip to content

Commit

Permalink
refactor: apply suggestions from pyupgrade (#2361)
Browse files Browse the repository at this point in the history
This PR refactors the codebase with Ruff's pyupgrade check, based on pyupgrade. Not all suggestions are applied, and some manual edits were applied in addition to the affected code. Removing target-version from the ruff options allows this to be automatically evaluated from pyproject.toml.

The rules that were applied include:

- UP004 (useless-object-inheritance)
- UP006 (non-pep585-annotation) - see PEP 585 for details; this was not applied to get_modflow.py to maintain it's compatibility for older Python versions in stand-alone mode
- UP018 (native-literals)
- UP034 (extraneous-parentheses)
- UP035 (deprecated-import)

Meanwhile, these rules were somewhat ignored:

- UP031,UP032: related to upgrading to f-strings. Ignored since these could involve much more string and message related refactoring to adjacent code. However, a few upgraded f-strings are upgraded where it looks simple, and in user-facing docs.
- UP015: for redundant file modes. Kept default file modes (e.g. open(..., "r") to keep it more clear, e.g. when a file pointer object is left open for reading (and then closed many lines further down, as is often done with legacy flopy code)
  • Loading branch information
mwtoews authored Nov 11, 2024
1 parent 4e09064 commit a5545c6
Show file tree
Hide file tree
Showing 41 changed files with 133 additions and 158 deletions.
14 changes: 3 additions & 11 deletions .docs/groundwater_paper/scripts/uspb_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,9 @@ def cf_model(model, k, i, j, base, Q=-100):
# write some summary information
fs.write(f"Problem size: {nrow} rows and {ncol} columns.\n")
fs.write(
"Capture fraction analysis performed every {} rows and columns.\n".format(
nstep
)
)
fs.write(
"Maximum number of analyses: {} rows and {} columns.\n".format(
nrow2, ncol2
)
f"Capture fraction analysis performed every {nstep} rows and columns.\n"
)
fs.write(f"Maximum number of analyses: {nrow2} rows and {ncol2} columns.\n")

# create array to store capture fraction data (subset of model)
cf_array = np.empty((10, nrow2, ncol2), dtype=float)
Expand All @@ -131,9 +125,7 @@ def cf_model(model, k, i, j, base, Q=-100):
if ibound[i, j] < 1:
sys.stdout.write(".")
else:
line = "\nrow {} of {} - col {} of {}\n".format(
icnt + 1, nrow2, jcnt + 1, ncol2
)
line = f"\nrow {icnt + 1} of {nrow2} - col {jcnt + 1} of {ncol2}\n"
fs.write(line)
sys.stdout.write(line)
s0 = time.time()
Expand Down
36 changes: 10 additions & 26 deletions .docs/groundwater_paper/scripts/uspb_capture_par.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ def copy_files(ml, nproc):
os.makedirs(cf_pths[idx])
filelist = [f for f in os.listdir(cf_pths[0])]
sys.stdout.write(
"copying files from {} to {}\n".format(
cf_pths[0], cf_pths[idx]
)
f"copying files from {cf_pths[0]} to {cf_pths[idx]}\n"
)
for f in filelist:
if os.path.splitext(f)[1].lower() in exclude:
Expand Down Expand Up @@ -179,9 +177,7 @@ def cf_model(imod, ion, nmax, k, i, j, Qt, base, hdry):
sys.stdout.write(f" model number {imod} working directory: {pth}\n")
make_well(pth, k, i, j, Qt)
success, elt = run_model(pth)
line = "\nModel run: {} of {} (model number {})\n".format(
ion + 1, nmax, imod
)
line = f"\nModel run: {ion + 1} of {nmax} (model number {imod})\n"
line += f" row {i + 1} - col {j + 1}\n"
line += f" {elt}\n"
# get the results
Expand Down Expand Up @@ -211,14 +207,12 @@ def cf_model(imod, ion, nmax, k, i, j, Qt, base, hdry):
]
v[idx] = ((v1.sum() + v2.sum() + v3.sum()) - base) / (-Qt)
except:
line += " Error: Model run: {} of {} (model number {}) - ".format(
ion + 1, nmax, imod
)
line += f" Error: Model run: {ion + 1} of {nmax} (model number {imod}) - "
line += "could not process model results.\n"
v[:] = np.nan
else:
line += " Error: Model run: {} of {} (model number {}) ".format(
ion + 1, nmax, imod
line += (
f" Error: Model run: {ion + 1} of {nmax} (model number {imod}) "
)
line += "did not execute successfully\n"
v[:] = np.nan
Expand All @@ -232,15 +226,11 @@ def doit():
ncores = mp.cpu_count()
if nproc > ncores:
sys.stdout.write(
"Requested {} cores but only {} cores are available.\n\n\n".format(
nproc, ncores
)
f"Requested {nproc} cores but only {ncores} cores are available.\n\n\n"
)
else:
sys.stdout.write(
"Requested {} cores and {} cores are available.\n\n\n".format(
nproc, ncores
)
f"Requested {nproc} cores and {ncores} cores are available.\n\n\n"
)

# paths
Expand Down Expand Up @@ -275,14 +265,10 @@ def doit():
# write some summary information
fs.write(f"Problem size: {nrow} rows and {ncol} columns.\n")
fs.write(
"Capture fraction analysis performed every {} rows and columns.\n".format(
nstep
)
f"Capture fraction analysis performed every {nstep} rows and columns.\n"
)
fs.write(
"Maximum number of analyses: {} rows and {} columns.\n".format(
nrow2, ncol2
)
f"Maximum number of analyses: {nrow2} rows and {ncol2} columns.\n"
)

# create array to store capture fraction data (subset of model)
Expand Down Expand Up @@ -359,9 +345,7 @@ def doit():
f"USPB_capture_fraction_{nstep:02d}_{idx + 1:02d}.dat",
)
sys.stdout.write(
"saving capture fraction data to...{}\n".format(
os.path.basename(fn)
)
f"saving capture fraction data to...{os.path.basename(fn)}\n"
)
np.savetxt(fn, cf_array[idx, :, :], delimiter=" ")

Expand Down
3 changes: 1 addition & 2 deletions autotest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from importlib import metadata
from pathlib import Path
from platform import system
from typing import List

import matplotlib.pyplot as plt
import pytest
Expand Down Expand Up @@ -52,7 +51,7 @@ def flopy_data_path() -> Path:


@pytest.fixture(scope="session")
def example_shapefiles(example_data_path) -> List[Path]:
def example_shapefiles(example_data_path) -> list[Path]:
return [f.resolve() for f in (example_data_path / "prj_test").glob("*")]


Expand Down
10 changes: 5 additions & 5 deletions autotest/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
import shutil
from pathlib import Path
from typing import List

import matplotlib.pyplot as plt
import numpy as np
Expand Down Expand Up @@ -56,7 +55,7 @@
import pyproj


def namfiles() -> List[Path]:
def namfiles() -> list[Path]:
mf2005_path = get_example_data_path() / "mf2005_test"
return list(mf2005_path.rglob("*.nam"))

Expand Down Expand Up @@ -998,9 +997,10 @@ def test_export_mf6_shp(function_tmpdir):
# Compare exported riv shapefiles
riv.export(function_tmpdir / "riv.shp")
riv6.export(function_tmpdir / "riv6.shp")
with Reader(function_tmpdir / "riv.shp") as riv_shp, Reader(
function_tmpdir / "riv6.shp"
) as riv6_shp:
with (
Reader(function_tmpdir / "riv.shp") as riv_shp,
Reader(function_tmpdir / "riv6.shp") as riv6_shp,
):
assert list(riv_shp.shapeRecord(-1).record) == list(
riv6_shp.shapeRecord(-1).record
)
Expand Down
2 changes: 1 addition & 1 deletion autotest/test_generate_classes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import sys
from collections.abc import Iterable
from os import environ
from pathlib import Path
from platform import system
from pprint import pprint
from typing import Iterable
from warnings import warn

import pytest
Expand Down
8 changes: 4 additions & 4 deletions autotest/test_lake_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,8 @@ def test_embedded_lak_prudic(example_data_path):
nlay = 8 # Number of layers
nrow = 36 # Number of rows
ncol = 23 # Number of columns
delr = float(405.665) # Column width ($ft$)
delc = float(403.717) # Row width ($ft$)
delr = 405.665 # Column width ($ft$)
delc = 403.717 # Row width ($ft$)
delv = 15.0 # Layer thickness ($ft$)
top = 100.0 # Top of the model ($ft$)

Expand Down Expand Up @@ -606,8 +606,8 @@ def test_embedded_lak_prudic_mixed(example_data_path):
nlay = 8 # Number of layers
nrow = 36 # Number of rows
ncol = 23 # Number of columns
delr = float(405.665) # Column width ($ft$)
delc = float(403.717) # Row width ($ft$)
delr = 405.665 # Column width ($ft$)
delc = 403.717 # Row width ($ft$)
delv = 15.0 # Layer thickness ($ft$)
top = 100.0 # Top of the model ($ft$)

Expand Down
6 changes: 4 additions & 2 deletions autotest/test_mbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ def test_resolve_exe_by_rel_path(function_tmpdir, use_ext, forgive):
assert which(actual)

# check behavior if exe DNE
with pytest.warns(UserWarning) if forgive else pytest.raises(
FileNotFoundError
with (
pytest.warns(UserWarning)
if forgive
else pytest.raises(FileNotFoundError)
):
assert not resolve_exe("../bin/mf2005", forgive)

Expand Down
1 change: 0 additions & 1 deletion autotest/test_modflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os
import shutil
from pathlib import Path
from typing import Dict

import numpy as np
import pandas as pd
Expand Down
2 changes: 1 addition & 1 deletion autotest/test_mp7.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ def test_mp7bas_porosity(ex01_mf6_model, porosity_type):
# Initialize porosity array based on dim of dis.botm
# lay_1=0.35, lay_2=0.30, lay_3=0.25
porosity = np.array([[[0.35]], [[0.30]], [[0.25]]]) * np.ones(
(gwf.dis.botm.array.shape)
gwf.dis.botm.array.shape
)
# Diversify porosity values, adjust both halves of the model
porosity[:, :, : porosity.shape[2] // 2] -= 0.05
Expand Down
4 changes: 2 additions & 2 deletions flopy/export/netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ def __init__(
self.log("initializing attributes")
self.nc_crs_str = "epsg:4326"
self.nc_crs_longname = "https://www.opengis.net/def/crs/EPSG/0/4326"
self.nc_semi_major = float(6378137.0)
self.nc_inverse_flat = float(298.257223563)
self.nc_semi_major = 6378137.0
self.nc_inverse_flat = 298.257223563

self.global_attributes = {}
self.global_attributes["namefile"] = self.model.namefile
Expand Down
4 changes: 2 additions & 2 deletions flopy/export/shapefile_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import sys
import warnings
from pathlib import Path
from typing import List, Optional, Union
from typing import Optional, Union
from warnings import warn

import numpy as np
Expand Down Expand Up @@ -489,7 +489,7 @@ def shape_attr_name(name, length=6, keep_layer=False):
return n


def enforce_10ch_limit(names: List[str], warnings: bool = True) -> List[str]:
def enforce_10ch_limit(names: list[str], warnings: bool = True) -> list[str]:
"""Enforce 10 character limit for fieldnames.
Add suffix for duplicate names starting at 0.
Expand Down
6 changes: 3 additions & 3 deletions flopy/mbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from pathlib import Path
from shutil import which
from subprocess import PIPE, STDOUT, Popen
from typing import List, Optional, Tuple, Union
from typing import Optional, Union
from warnings import warn

import numpy as np
Expand Down Expand Up @@ -1395,7 +1395,7 @@ def run_model(
pause=False,
report=False,
normal_msg="normal termination",
) -> Tuple[bool, List[str]]:
) -> tuple[bool, list[str]]:
"""
This method will run the model using subprocess.Popen.
Expand Down Expand Up @@ -1667,7 +1667,7 @@ def run_model(
use_async=False,
cargs=None,
custom_print=None,
) -> Tuple[bool, List[str]]:
) -> tuple[bool, list[str]]:
"""
Run the model using subprocess.Popen, optionally collecting stdout and printing
timestamped progress. Model workspace, namefile, executable to use, and several
Expand Down
2 changes: 1 addition & 1 deletion flopy/mf6/mfpackage.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def write_header(self, fd):
if len(self.data_items) > 1:
for data_item in self.data_items[1:]:
entry = data_item.get_file_entry(values_only=True)
fd.write("%s" % (entry.rstrip()))
fd.write(str(entry).rstrip())
if self.get_comment().text:
fd.write(" ")
self.get_comment().write(fd)
Expand Down
8 changes: 4 additions & 4 deletions flopy/mf6/mfsimbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
import warnings
from pathlib import Path
from typing import List, Optional, Union, cast
from typing import Optional, Union, cast

import numpy as np

Expand Down Expand Up @@ -1255,12 +1255,12 @@ def load_package(
return package

def register_ims_package(
self, solution_file: MFPackage, model_list: Union[str, List[str]]
self, solution_file: MFPackage, model_list: Union[str, list[str]]
):
self.register_solution_package(solution_file, model_list)

def register_solution_package(
self, solution_file: MFPackage, model_list: Union[str, List[str]]
self, solution_file: MFPackage, model_list: Union[str, list[str]]
):
"""
Register a solution package with the simulation.
Expand Down Expand Up @@ -2642,7 +2642,7 @@ def _is_in_solution_group(self, item, index, any_idx_after=False):

def plot(
self,
model_list: Optional[Union[str, List[str]]] = None,
model_list: Optional[Union[str, list[str]]] = None,
SelPackList=None,
**kwargs,
):
Expand Down
4 changes: 2 additions & 2 deletions flopy/mf6/utils/model_splitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
}


class Mf6Splitter(object):
class Mf6Splitter:
"""
A class for splitting a single model into a multi-model simulation
Expand Down Expand Up @@ -2493,7 +2493,7 @@ def _remap_obs(self, package, mapped_data, remapper, pkg_type=None):
for mkey, model in self._model_dict.items():
idx = np.asarray(new_model2 == mkey).nonzero()
tmp_node = new_node2[idx]
cidx = np.asarray((tmp_node != None)).nonzero() # noqa: E711
cidx = np.asarray(tmp_node != None).nonzero() # noqa: E711
tmp_cellid = model.modelgrid.get_lrc(
tmp_node[cidx].to_list()
)
Expand Down
4 changes: 2 additions & 2 deletions flopy/mfusg/mfusgdisu.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,8 @@ def load(cls, f, model, ext_unit_dict=None, check=True):

if model.version != "mfusg":
print(
"Warning: model version was reset from '{}' to 'mfusg' "
"in order to load a DISU file".format(model.version)
f"Warning: model version was reset from '{model.version}' "
"to 'mfusg' in order to load a DISU file"
)
model.version = "mfusg"

Expand Down
4 changes: 2 additions & 2 deletions flopy/mfusg/mfusgsms.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ def load(cls, f, model, ext_unit_dict=None):

if model.version != "mfusg":
print(
"Warning: model version was reset from '{}' to 'mfusg' "
"in order to load a SMS file".format(model.version)
f"Warning: model version was reset from '{model.version}' "
"to 'mfusg' in order to load a SMS file"
)
model.version = "mfusg"

Expand Down
Loading

0 comments on commit a5545c6

Please sign in to comment.