diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7ab2dbd8..bb04ef6c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: hooks: - id: flake8 additional_dependencies: - # - flake8-bugbear + - flake8-bugbear - flake8-comprehensions - flake8-simplify exclude: ^docs/source/pyplots/guides/.*$ diff --git a/deltametrics/cube.py b/deltametrics/cube.py index b47b3a96..bb5078a6 100644 --- a/deltametrics/cube.py +++ b/deltametrics/cube.py @@ -40,7 +40,7 @@ class BaseCube(abc.ABC): """ - def __init__(self, data, read=[], varset=None, dimensions=None): + def __init__(self, data, read=(), varset=None, dimensions=None): """Initialize the BaseCube. Parameters @@ -579,7 +579,8 @@ def show_plan(self, *args, **kwargs): "alternatives. To quickly show a planform slice of a cube, you " "can use `quick_show()` with a similar API. The `show_planform` " "method implements more features, but requires instantiating a " - "`Planform` object first. Passing arguments to `quick_show`." + "`Planform` object first. Passing arguments to `quick_show`.", + stacklevel=2, ) # pass `t` arg to `idx` for legacy if "t" in kwargs.keys(): @@ -643,7 +644,7 @@ class DataCube(BaseCube): """ def __init__( - self, data, read=[], varset=None, stratigraphy_from=None, dimensions=None + self, data, read=(), varset=None, stratigraphy_from=None, dimensions=None ): """Initialize the BaseCube. @@ -888,7 +889,7 @@ def from_DataCube( def __init__( self, data, - read=[], + read=(), varset=None, stratigraphy_from=None, sigma_dist=None, diff --git a/deltametrics/io.py b/deltametrics/io.py index 769f401c..5bdebcb8 100644 --- a/deltametrics/io.py +++ b/deltametrics/io.py @@ -219,7 +219,7 @@ def connect(self): # open the dataset _dataset = xr.open_dataset(self.data_path, engine=_engine) except Exception as e: - raise TypeError(f"File format out of scope for DeltaMetrics: {e}") + raise TypeError(f"File format out of scope for DeltaMetrics: {e}") from e # try to find if coordinates have been preconfigured _coords_list = list(_dataset.coords) @@ -246,6 +246,7 @@ def connect(self): "with DeltaMetrics. This warning may be replaced " "with an Error in a future version.", UserWarning, + stacklevel=2, ) else: # coordinates were not found and are not being set @@ -270,7 +271,9 @@ def connect(self): self.meta = _meta except OSError: warnings.warn( - "No associated metadata was found in the given data file.", UserWarning + "No associated metadata was found in the given data file.", + UserWarning, + stacklevel=2, ) self.meta = None @@ -381,7 +384,7 @@ def get_known_coords(self, dimensions): # get the coordinates and dimensions from the data self.dims = under.dims self.coords = [under.coords[dim].data for dim in self.dims] - self.dimensions = dict(zip(self.dims, self.coords)) + self.dimensions = dict(zip(self.dims, self.coords, strict=True)) # otherwise, check for the arguments passed elif not (dimensions is None): # if dimensions was passed, it must be a dictionary @@ -395,7 +398,7 @@ def get_known_coords(self, dimensions): raise ValueError("`dimensions` must contain three dimensions!") # use the dimensions keys as dims and the vals as coords # note, we check the size against the underlying a we go - for i, (k, v) in enumerate(dimensions.items()): + for i, k in enumerate(dimensions): if not (len(dimensions[k]) == under_shp[i]): raise ValueError( "Shape of `dimensions` at position {} was {}, " @@ -415,7 +418,7 @@ def get_known_coords(self, dimensions): self.coords = coords self.known_coords = self.dims - self.dimensions = dict(zip(self.dims, self.coords)) + self.dimensions = dict(zip(self.dims, self.coords, strict=True)) def connect(self, *args, **kwargs): """Connect to the data file. diff --git a/deltametrics/mask.py b/deltametrics/mask.py index 63531ad4..2ba59f92 100644 --- a/deltametrics/mask.py +++ b/deltametrics/mask.py @@ -279,7 +279,8 @@ def _check_deprecated_is_mask(self, is_mask): DeprecationWarning( "The `is_mask` argument is deprecated. " "It does not have any functionality." - ) + ), + stacklevel=2, ) def _check_deprecated_3d_input(self, args_0_shape): @@ -2107,13 +2108,11 @@ def _compute_mask(self, *args, **kwargs): from rivamap.singularity_index import applyMMSI as MMSI from rivamap.singularity_index import SingularityIndexFilters as SF from rivamap.delineate import extractCenterlines as eCL - except ImportError: + except ImportError as err: raise ImportError( "You must install the optional dependency: rivamap, to " "use the centerline extraction method." - ) - except Exception as e: - raise e + ) from err # pop the kwargs self.minScale = kwargs.pop("minScale", 1.5) diff --git a/deltametrics/mobility.py b/deltametrics/mobility.py index 7627608b..c511166e 100644 --- a/deltametrics/mobility.py +++ b/deltametrics/mobility.py @@ -137,14 +137,14 @@ def check_inputs(chmap, basevalues=None, basevalues_idx=None, window=None, basevalues = [np.argmin( np.abs(out_maps['chmap'].time.data - i)) for i in baselist] - except Exception: - raise TypeError('basevalues was not a list or list-able obj.') + except Exception as err: + raise TypeError('basevalues was not a list or list-able obj.') from err if (basevalues_idx is not None): try: basevalues_idx = list(basevalues_idx) - except Exception: - raise TypeError('basevalues_idx was not a list or list-able obj.') + except Exception as err: + raise TypeError('basevalues_idx was not a list or list-able obj.') from err if (basevalues is not None) and (basevalues_idx is not None): raise Warning( diff --git a/deltametrics/plan.py b/deltametrics/plan.py index 93efeabb..43f18eca 100644 --- a/deltametrics/plan.py +++ b/deltametrics/plan.py @@ -83,7 +83,8 @@ def name(self, var): "`Planform` object. To change the name of " "a Planform, you must set the attribute " "directly with `plan._name = 'name'`." - ) + ), + stacklevel=2, ) # do nothing @@ -1052,11 +1053,11 @@ def __init__(self, *args, **kwargs): elif isinstance(self.cube, BaseCube): try: self._max_disk = self.cube.meta["N0"].data - except Exception: + except Exception as err: raise TypeError( "Data cube does not contain metadata, you must " "specify the inlet size." - ) + ) from err else: raise TypeError( "Something went wrong. Check second input argument for " "inlet width." @@ -1322,7 +1323,7 @@ def compute_shoreline_roughness(shore_mask, land_mask, **kwargs): return rough -def compute_shoreline_length(shore_mask, origin=[0, 0], return_line=False): +def compute_shoreline_length(shore_mask, origin=(0, 0), return_line=False): """Compute the length of a shoreline from a mask of the shoreline. Algorithm attempts to determine the sorted coordinates of the shoreline @@ -1553,7 +1554,7 @@ def compute_shoreline_length(shore_mask, origin=[0, 0], return_line=False): return length -def compute_shoreline_distance(shore_mask, origin=[0, 0], return_distances=False): +def compute_shoreline_distance(shore_mask, origin=(0, 0), return_distances=False): """Compute mean and stddev distance from the delta apex to the shoreline. Algorithm computes the mean distance from the delta apex/origin to all @@ -1895,7 +1896,7 @@ def shaw_opening_angle_method( test_set_points = land_points else: raise ValueError( - f"Invalid option '{test_set}' for `test_set` parameter was supplied." + f"Invalid option {test_set!r} for `test_set` parameter was supplied." ) # Find convex hull @@ -1928,7 +1929,7 @@ def shaw_opening_angle_method( outside_hull_value = 0 else: raise ValueError( - f"Invalid option '{query_set}' for `query_set` parameter was supplied." + f"Invalid option {query_set!r} for `query_set` parameter was supplied." ) # Compute opening angle diff --git a/deltametrics/plot.py b/deltametrics/plot.py index b6e1bad1..0122558e 100644 --- a/deltametrics/plot.py +++ b/deltametrics/plot.py @@ -1088,7 +1088,7 @@ def _fill_steps(where, x=1, y=1, y0=0, **kwargs): Collection of `Rectangle` `Patch` objects. """ pl = [] - for i, pp in enumerate(np.argwhere(where[1:]).flatten()): + for _, pp in enumerate(np.argwhere(where[1:]).flatten()): _r = ptch.Rectangle((pp, y0), x, y, **kwargs) pl.append(_r) return coll.PatchCollection(pl, match_original=True) @@ -1399,7 +1399,7 @@ def aerial_view( datum=0, ax=None, ticks=False, - colorbar_kw={}, + colorbar_kw=None, return_im=False, **kwargs, ): @@ -1457,6 +1457,7 @@ def aerial_view( >>> fig, ax = plt.subplots() >>> _ = aerial_view(elevation_data, ax=ax) """ + colorbar_kw = {} if colorbar_kw is None else colorbar_kw if not ax: fig, ax = plt.subplots() diff --git a/deltametrics/sample_data/cube.py b/deltametrics/sample_data/cube.py index 7364c855..3022c4f4 100644 --- a/deltametrics/sample_data/cube.py +++ b/deltametrics/sample_data/cube.py @@ -18,5 +18,6 @@ def rcm8(): "Access is maintained here for backwards compatability, " "but will be removed in a future release.", DeprecationWarning, + stacklevel=2, ) return moved_rcm8() diff --git a/deltametrics/section.py b/deltametrics/section.py index 5bbd2fb1..4a5d1a5b 100644 --- a/deltametrics/section.py +++ b/deltametrics/section.py @@ -293,7 +293,8 @@ def name(self, var): "`Section` object. To change the name of " "a Section, you must set the attribute " "directly with `section._name = 'name'`." - ) + ), + stacklevel=2, ) # do nothing @@ -735,7 +736,7 @@ def show_trace(self, *args, ax=None, autoscale=False, **kwargs): lims = [ax.get_xlim(), ax.get_ylim()] # add the trace - ax.plot(_x, _y, label=_label, *args, **kwargs) + ax.plot(_x, _y, *args, label=_label, **kwargs) # if autscale is false, reset the axes if not autoscale: @@ -967,7 +968,8 @@ def __init__( "in a future release. Please use `distance_idx` and " "`length` to continue to specify cell indices, or " "use `distance` and `length` to specify " - "coordinate values." + "coordinate values.", + stacklevel=2, ) if direction == "strike": distance_idx = y @@ -1207,7 +1209,10 @@ def _compute_section_coords(self): @property def y(self): """Deprecated. Use :obj:`distance_idx`.""" - warnings.warn("`.y` is a deprecated attribute. Use `.distance_idx` instead.") + warnings.warn( + "`.y` is a deprecated attribute. Use `.distance_idx` instead.", + stacklevel=2, + ) return self._distance_idx @property @@ -1216,7 +1221,10 @@ def x(self): Start and end indices of section. """ - warnings.warn("`.x` is a deprecated attribute. Use `.length_idx` instead.") + warnings.warn( + "`.x` is a deprecated attribute. Use `.length_idx` instead.", + stacklevel=2, + ) return self._length_idx @@ -1418,7 +1426,10 @@ def _compute_section_coords(self): @property def y(self): """Deprecated. Use :obj:`length_idx`.""" - warnings.warn("`.y` is a deprecated attribute. Use `.length_idx` instead.") + warnings.warn( + "`.y` is a deprecated attribute. Use `.length_idx` instead.", + stacklevel=2, + ) return self._length_idx @property @@ -1427,7 +1438,10 @@ def x(self): Start and end indices of section. """ - warnings.warn("`.x` is a deprecated attribute. Use `.distance_idx` instead.") + warnings.warn( + "`.x` is a deprecated attribute. Use `.distance_idx` instead.", + stacklevel=2, + ) return self._distance_idx @@ -1602,8 +1616,10 @@ def _compute_section_coords(self): # try and guess the value (should issue a warning?) # if no field called 'eta'?? this will fail. warnings.warn( - "Trying to guess origin distance from dim1==0. " - "This is unlikely to work for data not generated from pyDeltaRCM." + "Trying to guess origin distance from dim1==0." + " This is unlikely to work for data not generated from" + " pyDeltaRCM.", + stacklevel=2, ) land_width = np.minimum( guess_land_width_from_land( @@ -1852,8 +1868,10 @@ def _compute_section_coords(self): # try and guess the value (should issue a warning?) # if no field called 'eta'?? this will fail. warnings.warn( - "Trying to guess origin distance from dim1==0. " - "This is unlikely to work for data not generated from pyDeltaRCM." + "Trying to guess origin distance from dim1==0." + " This is unlikely to work for data not generated from" + " pyDeltaRCM.", + stacklevel=2, ) land_width = np.minimum( guess_land_width_from_land( diff --git a/deltametrics/strat.py b/deltametrics/strat.py index d0927236..077dfceb 100644 --- a/deltametrics/strat.py +++ b/deltametrics/strat.py @@ -1062,8 +1062,12 @@ def _determine_strat_coordinates(elev, z=None, dz=None, nz=None): # if nothing is supplied if (dz is None) and (z is None) and (nz is None): warnings.warn( - UserWarning('No specification for stratigraphy spacing ' - 'was supplied. Default is to use `dz=0.1`')) + UserWarning( + "No specification for stratigraphy spacing" + " was supplied. Default is to use `dz=0.1`" + ), + stacklevel=2, + ) # set the default option when nothing is supplied dz = 0.1 diff --git a/deltametrics/utils.py b/deltametrics/utils.py index 0426fbff..ec211cda 100644 --- a/deltametrics/utils.py +++ b/deltametrics/utils.py @@ -69,7 +69,7 @@ def decorator(*args, **kwargs): try: return func(*args, **kwargs) except AttributeError as e: - raise NoStratigraphyError(e) + raise NoStratigraphyError(e) from e return decorator @@ -110,7 +110,7 @@ def _attribute_checker(self, checklist): raise TypeError('Checklist must be of type `list`,' 'but was type: %s' % type(checklist)) - for c, check in enumerate(checklist): + for _, check in enumerate(checklist): has = getattr(self, check, None) if has is None: att_dict[check] = False @@ -119,7 +119,7 @@ def _attribute_checker(self, checklist): log_list = list(att_dict.values()) log_form = [value for string, value in - zip(log_list, att_dict.keys()) if not string] + zip(log_list, att_dict.keys(), strict=True) if not string] if not all(log_list): raise RuntimeError('Required attribute(s) not assigned: ' + str(log_form)) diff --git a/tests/test_plot.py b/tests/test_plot.py index 38da1d71..3a6a2c42 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -761,7 +761,7 @@ def test_limits_zero_one(self): def test_scale_down_red(self): red = (1.0, 0.0, 0.0) # initial color red scales = np.arange(1, 0, -0.05) # from 1 to 0.05 - for s, scale in enumerate(scales): + for _, scale in enumerate(scales): darker_red = _scale_lightness(red, scale) assert darker_red[0] == pytest.approx(scale) @@ -790,7 +790,7 @@ def test_one_histogram_with_ax(self): def test_multiple_no_sets(self): sets = [np.histogram(np.random.normal(lc, s, size=500), bins=self.bins, density=True) for lc, s in - zip(self.locs, self.scales)] + zip(self.locs, self.scales, strict=True)] fig, ax = plt.subplots() show_histograms(*sets, ax=ax) plt.close() @@ -798,7 +798,7 @@ def test_multiple_no_sets(self): def test_multiple_no_sets_alphakwarg(self): sets = [np.histogram(np.random.normal(lc, s, size=500), bins=self.bins, density=True) for lc, s in - zip(self.locs, self.scales)] + zip(self.locs, self.scales, strict=True)] fig, ax = plt.subplots() show_histograms(*sets, ax=ax, alpha=0.4) plt.close() @@ -806,14 +806,13 @@ def test_multiple_no_sets_alphakwarg(self): def test_multiple_with_sets(self): sets = [np.histogram(np.random.normal(lc, s, size=500), bins=self.bins, density=True) for lc, s in - zip(self.locs, self.scales)] + zip(self.locs, self.scales, strict=True)] fig, ax = plt.subplots() show_histograms(*sets, sets=[0, 0, 1, 1, 2], ax=ax) plt.close() with pytest.raises(ValueError, match=r'Number of histogram tuples*.'): # input lengths must match show_histograms(*sets, sets=[0, 1], ax=ax) - plt.close() class TestAerialView: diff --git a/tests/test_section.py b/tests/test_section.py index 2115cd06..6995bbf1 100644 --- a/tests/test_section.py +++ b/tests/test_section.py @@ -84,7 +84,7 @@ def test_StrikeSection_register_section_distance_idx(self): rcm8cube.register_section( "testname", StrikeSection(distance_idx=5, name="TESTING") ) - assert rcm8cube.sections["testname"].name == "TESTING" + assert rcm8cube.sections["testname"].name == "TESTING" _sect = rcm8cube.register_section( "test", StrikeSection(distance_idx=5), return_section=True ) @@ -238,7 +238,7 @@ def test_register_section(self): rcm8cube.register_section( "test2", PathSection(path_idx=self.test_path, name="trial") ) - assert rcm8cube.sections["test2"].name == "trial" + assert rcm8cube.sections["test2"].name == "trial" _section = rcm8cube.register_section( "test", PathSection(path_idx=self.test_path), return_section=True ) @@ -372,7 +372,7 @@ def test_register_section(self): rcm8cube.register_section( "test2", CircularSection(radius_idx=31, name="diff") ) - assert rcm8cube.sections["test2"].name == "diff" + assert rcm8cube.sections["test2"].name == "diff" rcm8cube.register_section("test3", CircularSection()) assert rcm8cube.sections["test3"]._radius_idx == rcm8cube.shape[1] // 2 _section = rcm8cube.register_section( @@ -498,7 +498,7 @@ def test_register_section(self): rcm8cube.register_section( "test2", RadialSection(azimuth=30, name="notthesame") ) - assert rcm8cube.sections["test2"].name == "notthesame" + assert rcm8cube.sections["test2"].name == "notthesame" _section = rcm8cube.register_section( "test", RadialSection(azimuth=30), return_section=True ) @@ -1206,7 +1206,7 @@ def test_DipSection_register_section_distance_idx(self): rcm8cube.register_section( "testname", DipSection(distance_idx=150, name="TESTING") ) - assert rcm8cube.sections["testname"].name == "TESTING" + assert rcm8cube.sections["testname"].name == "TESTING" _sect = rcm8cube.register_section( "test", DipSection(distance_idx=150), return_section=True )