From 5116a3d7c45df9bc53f56093d1ac6eac569f39f4 Mon Sep 17 00:00:00 2001 From: Virgile Andreani Date: Mon, 16 Sep 2024 20:07:30 -0400 Subject: [PATCH] Fix B904: raise from within except --- asv_bench/benchmarks/__init__.py | 8 ++++---- asv_bench/benchmarks/dataset_io.py | 4 ++-- ci/min_deps_check.py | 4 ++-- xarray/backends/api.py | 16 ++++++++-------- xarray/backends/netCDF4_.py | 6 +++--- xarray/backends/scipy_.py | 6 ++++-- xarray/backends/zarr.py | 6 ++++-- xarray/coding/cftimeindex.py | 12 ++++++------ xarray/coding/times.py | 12 ++++++------ xarray/core/combine.py | 2 +- xarray/core/common.py | 6 ++++-- xarray/core/concat.py | 4 ++-- xarray/core/dataarray.py | 10 +++++----- xarray/core/dataset.py | 14 +++++++++----- xarray/core/duck_array_ops.py | 8 ++++---- xarray/core/extensions.py | 4 ++-- xarray/core/groupby.py | 4 ++-- xarray/core/indexes.py | 4 ++-- xarray/core/indexing.py | 2 +- xarray/core/missing.py | 4 ++-- xarray/core/utils.py | 4 ++-- xarray/core/variable.py | 16 +++++++++------- xarray/namedarray/core.py | 6 ++++-- xarray/plot/utils.py | 4 ++-- xarray/tutorial.py | 8 ++++---- 25 files changed, 94 insertions(+), 80 deletions(-) diff --git a/asv_bench/benchmarks/__init__.py b/asv_bench/benchmarks/__init__.py index aa600c88003..697fcb58494 100644 --- a/asv_bench/benchmarks/__init__.py +++ b/asv_bench/benchmarks/__init__.py @@ -18,15 +18,15 @@ def decorator(func): def requires_dask(): try: import dask # noqa: F401 - except ImportError: - raise NotImplementedError() + except ImportError as err: + raise NotImplementedError() from err def requires_sparse(): try: import sparse # noqa: F401 - except ImportError: - raise NotImplementedError() + except ImportError as err: + raise NotImplementedError() from err def randn(shape, frac_nan=None, chunks=None, seed=0): diff --git a/asv_bench/benchmarks/dataset_io.py b/asv_bench/benchmarks/dataset_io.py index 6031619e4ab..8ab367b76e0 100644 --- a/asv_bench/benchmarks/dataset_io.py +++ b/asv_bench/benchmarks/dataset_io.py @@ -606,8 +606,8 @@ def setup(self): try: import distributed - except ImportError: - raise NotImplementedError() + except ImportError as err: + raise NotImplementedError() from err self.client = distributed.Client() self.write = create_delayed_write() diff --git a/ci/min_deps_check.py b/ci/min_deps_check.py index 6981a69d96c..d6c845615d4 100755 --- a/ci/min_deps_check.py +++ b/ci/min_deps_check.py @@ -68,8 +68,8 @@ def parse_requirements(fname) -> Iterator[tuple[str, int, int, int | None]]: try: version_tup = tuple(int(x) for x in version.split(".")) - except ValueError: - raise ValueError("non-numerical version: " + row) + except ValueError as err: + raise ValueError("non-numerical version: " + row) from err if len(version_tup) == 2: yield (pkg, *version_tup, None) # type: ignore[misc] diff --git a/xarray/backends/api.py b/xarray/backends/api.py index 192102c5ba3..e9e3e9beacd 100644 --- a/xarray/backends/api.py +++ b/xarray/backends/api.py @@ -99,11 +99,11 @@ def _get_default_engine_remote_uri() -> Literal["netcdf4", "pydap"]: import pydap # noqa: F401 engine = "pydap" - except ImportError: + except ImportError as err: raise ValueError( "netCDF4 or pydap is required for accessing " "remote datasets via OPeNDAP" - ) + ) from err return engine @@ -112,8 +112,8 @@ def _get_default_engine_gz() -> Literal["scipy"]: import scipy # noqa: F401 engine: Final = "scipy" - except ImportError: # pragma: no cover - raise ValueError("scipy is required for accessing .gz files") + except ImportError as err: # pragma: no cover + raise ValueError("scipy is required for accessing .gz files") from err return engine @@ -128,11 +128,11 @@ def _get_default_engine_netcdf() -> Literal["netcdf4", "scipy"]: import scipy.io.netcdf # noqa: F401 engine = "scipy" - except ImportError: + except ImportError as err: raise ValueError( "cannot read or write netCDF files without " "netCDF4-python or scipy installed" - ) + ) from err return engine @@ -1374,8 +1374,8 @@ def to_netcdf( try: store_open = WRITEABLE_STORES[engine] - except KeyError: - raise ValueError(f"unrecognized engine for to_netcdf: {engine!r}") + except KeyError as err: + raise ValueError(f"unrecognized engine for to_netcdf: {engine!r}") from err if format is not None: format = format.upper() # type: ignore[assignment] diff --git a/xarray/backends/netCDF4_.py b/xarray/backends/netCDF4_.py index af2c15495d7..d1c3719905c 100644 --- a/xarray/backends/netCDF4_.py +++ b/xarray/backends/netCDF4_.py @@ -111,7 +111,7 @@ def _getitem(self, key): with self.datastore.lock: original_array = self.get_array(needs_lock=False) array = getitem(original_array, key) - except IndexError: + except IndexError as err: # Catch IndexError in netCDF4 and return a more informative # error message. This is most often called when an unsorted # indexer is used before the data is loaded from disk. @@ -120,7 +120,7 @@ def _getitem(self, key): "is not valid on netCDF4.Variable object. Try loading " "your data into memory first by calling .load()." ) - raise IndexError(msg) + raise IndexError(msg) from err return array @@ -192,7 +192,7 @@ def _nc4_require_group(ds, group, mode, create_group=_netcdf4_create_group): ds = create_group(ds, key) else: # wrap error to provide slightly more helpful message - raise OSError(f"group not found: {key}", e) + raise OSError(f"group not found: {key}", e) from e return ds diff --git a/xarray/backends/scipy_.py b/xarray/backends/scipy_.py index 83031e1ef8b..e77443061fe 100644 --- a/xarray/backends/scipy_.py +++ b/xarray/backends/scipy_.py @@ -114,7 +114,9 @@ def _open_scipy_netcdf(filename, mode, mmap, version): # TODO: gzipped loading only works with NetCDF3 files. errmsg = e.args[0] if "is not a valid NetCDF 3 file" in errmsg: - raise ValueError("gzipped file loading only supports NetCDF 3 files.") + raise ValueError( + "gzipped file loading only supports NetCDF 3 files." + ) from e else: raise @@ -134,7 +136,7 @@ def _open_scipy_netcdf(filename, mode, mmap, version): $ pip install netcdf4 """ errmsg += msg - raise TypeError(errmsg) + raise TypeError(errmsg) from e else: raise diff --git a/xarray/backends/zarr.py b/xarray/backends/zarr.py index 2c39869c1e6..5a6b043eef8 100644 --- a/xarray/backends/zarr.py +++ b/xarray/backends/zarr.py @@ -1374,8 +1374,10 @@ def _get_open_params( RuntimeWarning, stacklevel=stacklevel, ) - except zarr.errors.GroupNotFoundError: - raise FileNotFoundError(f"No such file or directory: '{store}'") + except zarr.errors.GroupNotFoundError as err: + raise FileNotFoundError( + f"No such file or directory: '{store}'" + ) from err elif consolidated: # TODO: an option to pass the metadata_key keyword zarr_group = zarr.open_consolidated(store, **open_kwargs) diff --git a/xarray/coding/cftimeindex.py b/xarray/coding/cftimeindex.py index d3a0fbb3dba..e85fa2736b2 100644 --- a/xarray/coding/cftimeindex.py +++ b/xarray/coding/cftimeindex.py @@ -439,8 +439,8 @@ def _get_string_slice(self, key): parsed, resolution = _parse_iso8601_with_reso(self.date_type, key) try: loc = self._partial_date_slice(resolution, parsed) - except KeyError: - raise KeyError(key) + except KeyError as err: + raise KeyError(key) from err return loc def _get_nearest_indexer(self, target, limit, tolerance): @@ -593,21 +593,21 @@ def __sub__(self, other): if _contains_cftime_datetimes(np.array(other)): try: return pd.TimedeltaIndex(np.array(self) - np.array(other)) - except OUT_OF_BOUNDS_TIMEDELTA_ERRORS: + except OUT_OF_BOUNDS_TIMEDELTA_ERRORS as err: raise ValueError( "The time difference exceeds the range of values " "that can be expressed at the nanosecond resolution." - ) + ) from err return NotImplemented def __rsub__(self, other): try: return pd.TimedeltaIndex(other - np.array(self)) - except OUT_OF_BOUNDS_TIMEDELTA_ERRORS: + except OUT_OF_BOUNDS_TIMEDELTA_ERRORS as err: raise ValueError( "The time difference exceeds the range of values " "that can be expressed at the nanosecond resolution." - ) + ) from err def to_datetimeindex(self, unsafe=False): """If possible, convert this index to a pandas.DatetimeIndex. diff --git a/xarray/coding/times.py b/xarray/coding/times.py index 9b8c4c761ba..3bcbc486064 100644 --- a/xarray/coding/times.py +++ b/xarray/coding/times.py @@ -216,7 +216,7 @@ def _decode_cf_datetime_dtype( try: result = decode_cf_datetime(example_value, units, calendar, use_cftime) - except Exception: + except Exception as err: calendar_msg = ( "the default calendar" if calendar is None else f"calendar {calendar!r}" ) @@ -225,7 +225,7 @@ def _decode_cf_datetime_dtype( "opening your dataset with decode_times=False or installing cftime " "if it is not installed." ) - raise ValueError(msg) + raise ValueError(msg) from err else: dtype = getattr(result, "dtype", np.dtype("object")) @@ -260,10 +260,10 @@ def _decode_datetime_with_pandas( # TODO: the strict enforcement of nanosecond precision Timestamps can be # relaxed when addressing GitHub issue #7493. ref_date = nanosecond_precision_timestamp(ref_date_str) - except ValueError: + except ValueError as err: # ValueError is raised by pd.Timestamp for non-ISO timestamp # strings, in which case we fall back to using cftime - raise OutOfBoundsDatetime + raise OutOfBoundsDatetime from err with warnings.catch_warnings(): warnings.filterwarnings("ignore", "invalid value encountered", RuntimeWarning) @@ -488,7 +488,7 @@ def cftime_to_nptime(times, raise_on_invalid: bool = True) -> np.ndarray: raise ValueError( f"Cannot convert date {t} to a date in the " f"standard calendar. Reason: {e}." - ) + ) from e else: dt = "NaT" new[i] = np.datetime64(dt) @@ -521,7 +521,7 @@ def convert_times(times, date_type, raise_on_invalid: bool = True) -> np.ndarray raise ValueError( f"Cannot convert date {t} to a date in the " f"{date_type(2000, 1, 1).calendar} calendar. Reason: {e}." - ) + ) from e else: dt = np.nan diff --git a/xarray/core/combine.py b/xarray/core/combine.py index c7dff9d249d..50cfd87076f 100644 --- a/xarray/core/combine.py +++ b/xarray/core/combine.py @@ -308,7 +308,7 @@ def _combine_1d( "xarray.combine_by_coords, or do it manually " "with xarray.concat, xarray.merge and " "xarray.align" - ) + ) from err else: raise else: diff --git a/xarray/core/common.py b/xarray/core/common.py index 44d89b8a2cf..e4c61a1bc12 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -241,8 +241,10 @@ def _get_axis_num(self: Any, dim: Hashable) -> int: _raise_if_any_duplicate_dimensions(self.dims) try: return self.dims.index(dim) - except ValueError: - raise ValueError(f"{dim!r} not found in array dimensions {self.dims!r}") + except ValueError as err: + raise ValueError( + f"{dim!r} not found in array dimensions {self.dims!r}" + ) from err @property def sizes(self: Any) -> Mapping[Hashable, int]: diff --git a/xarray/core/concat.py b/xarray/core/concat.py index 1133d8cc373..e137cff257f 100644 --- a/xarray/core/concat.py +++ b/xarray/core/concat.py @@ -252,8 +252,8 @@ def concat( try: first_obj, objs = utils.peek_at(objs) - except StopIteration: - raise ValueError("must supply at least one object to concatenate") + except StopIteration as err: + raise ValueError("must supply at least one object to concatenate") from err if compat not in _VALID_COMPAT: raise ValueError( diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 9256d10e5f0..4389c75c630 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -3860,11 +3860,11 @@ def to_pandas(self) -> Self | pd.Series | pd.DataFrame: constructors = {0: lambda x: x, 1: pd.Series, 2: pd.DataFrame} try: constructor = constructors[self.ndim] - except KeyError: + except KeyError as err: raise ValueError( f"Cannot convert arrays with {self.ndim} dimensions into " "pandas objects. Requires 2 or fewer dimensions." - ) + ) from err indexes = [self.get_index(dim) for dim in self.dims] return constructor(self.values, *indexes) # type: ignore[operator] @@ -4468,11 +4468,11 @@ def from_dict(cls, d: Mapping[str, Any]) -> Self: raise ValueError( "cannot convert dict when coords are missing the key " f"'{str(e.args[0])}'" - ) + ) from e try: data = d["data"] - except KeyError: - raise ValueError("cannot convert dict without the key 'data''") + except KeyError as err: + raise ValueError("cannot convert dict without the key 'data''") from err else: obj = cls(data, coords, d.get("dims"), d.get("name"), d.get("attrs")) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index a3ddab8bf3c..b68c5f81fd7 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -359,12 +359,12 @@ def _get_func_args(func, param_names): """ try: func_args = inspect.signature(func).parameters - except ValueError: + except ValueError as err: func_args = {} if not param_names: raise ValueError( "Unable to inspect `func` signature, and `param_names` was not provided." - ) + ) from err if param_names: params = param_names else: @@ -6213,8 +6213,10 @@ def drop_sel( labels_for_dim = np.asarray(labels_for_dim) try: index = self.get_index(dim) - except KeyError: - raise ValueError(f"dimension {dim!r} does not have coordinate labels") + except KeyError as err: + raise ValueError( + f"dimension {dim!r} does not have coordinate labels" + ) from err new_index = index.drop(labels_for_dim, errors=errors) ds = ds.loc[{dim: new_index}] return ds @@ -7747,7 +7749,9 @@ def from_dict(cls, d: Mapping[Any, Any]) -> Self: for k, v in variables } except KeyError as e: - raise ValueError(f"cannot convert dict without the key '{str(e.args[0])}'") + raise ValueError( + f"cannot convert dict without the key '{str(e.args[0])}'" + ) from e obj = cls(variable_dict) # what if coords aren't dims? diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index e4fe95a6118..95aba0441e2 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -451,10 +451,10 @@ def f(values, axis=None, skipna=None, **kwargs): try: # dask/dask#3133 dask sometimes needs dtype argument # if func does not accept dtype, then raises TypeError return func(values, axis=axis, dtype=values.dtype, **kwargs) - except (AttributeError, TypeError): + except (AttributeError, TypeError) as err: raise NotImplementedError( f"{name} is not yet implemented on dask arrays" - ) + ) from err f.__name__ = name return f @@ -592,10 +592,10 @@ def timedelta_to_numeric(value, datetime_unit="ns", dtype=float): elif isinstance(value, str): try: a = pd.to_timedelta(value) - except ValueError: + except ValueError as err: raise ValueError( f"Could not convert {value!r} to timedelta64 using pandas.to_timedelta" - ) + ) from err return py_timedelta_to_float(a, datetime_unit) else: raise TypeError( diff --git a/xarray/core/extensions.py b/xarray/core/extensions.py index 9ebbd564f4f..c235fae000a 100644 --- a/xarray/core/extensions.py +++ b/xarray/core/extensions.py @@ -37,11 +37,11 @@ def __get__(self, obj, cls): try: accessor_obj = self._accessor(obj) - except AttributeError: + except AttributeError as err: # __getattr__ on data object will swallow any AttributeErrors # raised when initializing the accessor, so we need to raise as # something else (GH933): - raise RuntimeError(f"error initializing {self._name!r} accessor.") + raise RuntimeError(f"error initializing {self._name!r} accessor.") from err cache[self._name] = accessor_obj return accessor_obj diff --git a/xarray/core/groupby.py b/xarray/core/groupby.py index d07ab9dcb17..0a1d11f8519 100644 --- a/xarray/core/groupby.py +++ b/xarray/core/groupby.py @@ -390,8 +390,8 @@ def _resolve_group( if isinstance(group, DataArray): try: align(obj, group, join="exact", copy=False) - except ValueError: - raise ValueError(error_msg) + except ValueError as err: + raise ValueError(error_msg) from err newgroup = group.copy(deep=False) newgroup.name = group.name or "group" diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index 35870064db5..5abc2129e3e 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -1206,12 +1206,12 @@ def sel(self, labels, method=None, tolerance=None) -> IndexSelResult: label_array = normalize_label(v, dtype=self.level_coords_dtype[k]) try: label_values[k] = as_scalar(label_array) - except ValueError: + except ValueError as err: # label should be an item not an array-like raise ValueError( "Vectorized selection is not " f"available along coordinate {k!r} (multi-index level)" - ) + ) from err has_slice = any([isinstance(v, slice) for v in label_values.values()]) diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index 06b4b9a475f..67912908a2b 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -1527,7 +1527,7 @@ def _safe_setitem(self, array, key: tuple[Any, ...], value: Any) -> None: raise ValueError( "Assignment destination is a view. " "Do you want to .copy() array first?" - ) + ) from exc else: raise exc diff --git a/xarray/core/missing.py b/xarray/core/missing.py index 0769208ed73..2df53b172f0 100644 --- a/xarray/core/missing.py +++ b/xarray/core/missing.py @@ -298,13 +298,13 @@ def get_clean_interp_index( # raise if index cannot be cast to a float (e.g. MultiIndex) try: index = index.values.astype(np.float64) - except (TypeError, ValueError): + except (TypeError, ValueError) as err: # pandas raises a TypeError # xarray/numpy raise a ValueError raise TypeError( f"Index {index.name!r} must be castable to float64 to support " f"interpolation or curve fitting, got {type(index).__name__}." - ) + ) from err return index diff --git a/xarray/core/utils.py b/xarray/core/utils.py index f8b4be2ee4a..3c1dee7a36d 100644 --- a/xarray/core/utils.py +++ b/xarray/core/utils.py @@ -570,8 +570,8 @@ def size(self: Any) -> int: def __len__(self: Any) -> int: try: return self.shape[0] - except IndexError: - raise TypeError("len() of unsized object") + except IndexError as err: + raise TypeError("len() of unsized object") from err class NDArrayMixin(NdimSizeLenMixin): diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 6f634621026..98a649b254b 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -132,8 +132,10 @@ def as_variable( elif isinstance(obj, tuple): try: dims_, data_, *attrs = obj - except ValueError: - raise ValueError(f"Tuple {obj} is not in the form (dims, data[, attrs])") + except ValueError as err: + raise ValueError( + f"Tuple {obj} is not in the form (dims, data[, attrs])" + ) from err if isinstance(data_, DataArray): raise TypeError( @@ -146,7 +148,7 @@ def as_variable( raise error.__class__( f"Variable {name!r}: Could not convert tuple of form " f"(dims, data[, attrs, encoding]): {obj} to Variable." - ) + ) from error elif utils.is_scalar(obj): obj = Variable([], obj) elif isinstance(obj, pd.Index | IndexVariable) and obj.name is not None: @@ -768,8 +770,8 @@ def _broadcast_indexes_vectorized(self, key): try: variables = _broadcast_compat_variables(*variables) - except ValueError: - raise IndexError(f"Dimensions of indexers mismatch: {key}") + except ValueError as err: + raise IndexError(f"Dimensions of indexers mismatch: {key}") from err out_key = [variable.data for variable in variables] out_dims = tuple(out_dims_set) @@ -896,8 +898,8 @@ def encoding(self) -> dict[Any, Any]: def encoding(self, value): try: self._encoding = dict(value) - except ValueError: - raise ValueError("encoding must be castable to a dictionary") + except ValueError as err: + raise ValueError("encoding must be castable to a dictionary") from err def reset_encoding(self) -> Self: warnings.warn( diff --git a/xarray/namedarray/core.py b/xarray/namedarray/core.py index 9bb7b36e745..d27850433ec 100644 --- a/xarray/namedarray/core.py +++ b/xarray/namedarray/core.py @@ -697,8 +697,10 @@ def _get_axis_num(self: Any, dim: Hashable) -> int: _raise_if_any_duplicate_dimensions(self.dims) try: return self.dims.index(dim) # type: ignore[no-any-return] - except ValueError: - raise ValueError(f"{dim!r} not found in array dimensions {self.dims!r}") + except ValueError as err: + raise ValueError( + f"{dim!r} not found in array dimensions {self.dims!r}" + ) from err @property def chunks(self) -> _Chunks | None: diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 334e5226c31..6d8deb5a66a 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -454,8 +454,8 @@ def get_axis( try: import matplotlib as mpl import matplotlib.pyplot as plt - except ImportError: - raise ImportError("matplotlib is required for plot.utils.get_axis") + except ImportError as err: + raise ImportError("matplotlib is required for plot.utils.get_axis") from err if figsize is not None: if ax is not None: diff --git a/xarray/tutorial.py b/xarray/tutorial.py index 82bb3940b98..0472584028a 100644 --- a/xarray/tutorial.py +++ b/xarray/tutorial.py @@ -60,22 +60,22 @@ def _check_netcdf_engine_installed(name): except ImportError: try: import netCDF4 # noqa - except ImportError: + except ImportError as err: raise ImportError( f"opening tutorial dataset {name} requires either scipy or " "netCDF4 to be installed." - ) + ) from err if version == 4: try: import h5netcdf # noqa except ImportError: try: import netCDF4 # noqa - except ImportError: + except ImportError as err: raise ImportError( f"opening tutorial dataset {name} requires either h5netcdf " "or netCDF4 to be installed." - ) + ) from err # idea borrowed from Seaborn